Merge branch 'v4-0-test' of git://git.samba.org/samba into 4-0-local
[samba.git] / source4 / dsdb / samdb / ldb_modules / samba3sam.c
index 0ee04330715cbdfea218e72772b62a23267e1693..3a666b5380fd1be42f35043a6fecc65a3cdc8035 100644 (file)
@@ -1,38 +1,46 @@
-/* 
+/*
    ldb database library - Samba3 SAM compatibility backend
 
    Copyright (C) Jelmer Vernooij 2005
+   Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
 */
 
 #include "includes.h"
-#include "ldb/modules/ldb_map.h"
 #include "ldb/include/ldb.h"
 #include "ldb/include/ldb_private.h"
-#include "librpc/gen_ndr/ndr_security.h"
+#include "ldb/include/ldb_errors.h"
+#include "ldb/ldb_map/ldb_map.h"
 #include "system/passwd.h"
 
-/* 
+#include "librpc/gen_ndr/ndr_security.h"
+#include "librpc/gen_ndr/ndr_samr.h"
+#include "librpc/ndr/libndr.h"
+#include "libcli/security/security.h"
+#include "libcli/security/proto.h"
+#include "lib/samba3/samba3.h"
+
+/*
  * sambaSID -> member  (dn!)
- * sambaSIDList -> member (dn!) 
- * sambaDomainName -> name 
- * sambaTrustPassword 
- * sambaUnixIdPool 
- * sambaIdmapEntry 
- * sambaAccountPolicy 
- * sambaSidEntry 
+ * sambaSIDList -> member (dn!)
+ * sambaDomainName -> name
+ * sambaTrustPassword
+ * sambaUnixIdPool
+ * sambaIdmapEntry
+ * sambaAccountPolicy
+ * sambaSidEntry
  * sambaAcctFlags -> systemFlags ?
  * sambaPasswordHistory  -> ntPwdHistory*/
 
 /* Not necessary:
  * sambaConfig
  * sambaShare
- * sambaConfigOption 
+ * sambaConfigOption
  * sambaNextGroupRid
  * sambaNextUserRid
  * sambaAlgorithmicRidBase
  */
 
-/* Not in Samba4: 
+/* Not in Samba4:
  * sambaKickoffTime
  * sambaPwdCanChange
  * sambaPwdMustChange
 /* In Samba4 but not in Samba3:
 */
 
-static void generate_hashes (struct ldb_module *module, const char *local_attr,        const struct ldb_message *local, struct ldb_message *remote_mp, struct ldb_message *remote_fb)
-{
-       const char *upwd = ldb_msg_find_string(local, local_attr, NULL);
-       struct ldb_val val;
-
-       if (!upwd)
-               return;
-
-       ldb_msg_add_string(module->ldb, remote_fb, local_attr, upwd);
-
-       val.length = 16;
-       val.data = talloc_zero_size(module, val.length);
-
-       E_md4hash(upwd, val.data);
-       ldb_msg_add_value(module->ldb, remote_mp, "sambaNTPassword", &val);
-                       
-       val.data = talloc_zero_size(module, val.length);
-       E_deshash(upwd, val.data);
-       ldb_msg_add_value(module->ldb, remote_mp, "sambaLMPassword", &val);
-}
-
-
-static struct ldb_message_element *generate_primaryGroupID(struct ldb_module *module, TALLOC_CTX *ctx, const char *attr, const struct ldb_message *remote)
+/* From a sambaPrimaryGroupSID, generate a primaryGroupID (integer) attribute */
+static struct ldb_message_element *generate_primaryGroupID(struct ldb_module *module, TALLOC_CTX *ctx, const char *local_attr, const struct ldb_message *remote)
 {
        struct ldb_message_element *el;
-       const char *sid = ldb_msg_find_string(remote, attr, NULL);
-
+       const char *sid = ldb_msg_find_attr_as_string(remote, "sambaPrimaryGroupSID", NULL);
+       const char *p;
+       
        if (!sid)
                return NULL;
 
-       if (strchr(sid, '-') == NULL)
+       p = strrchr(sid, '-');
+       if (!p)
                return NULL;
 
        el = talloc_zero(ctx, struct ldb_message_element);
        el->name = talloc_strdup(ctx, "primaryGroupID");
        el->num_values = 1;
        el->values = talloc_array(ctx, struct ldb_val, 1);
-       el->values[0].data = (uint8_t *)talloc_strdup(ctx, strchr(sid, '-')+1);
+       el->values[0].data = (uint8_t *)talloc_strdup(el->values, p+1);
        el->values[0].length = strlen((char *)el->values[0].data);
 
        return el;
@@ -95,19 +84,21 @@ static void generate_sambaPrimaryGroupSID(struct ldb_module *module, const char
        const struct ldb_val *sidval;
        char *sidstring;
        struct dom_sid *sid;
-       NTSTATUS status;
+       enum ndr_err_code ndr_err;
 
+       /* We need the domain, so we get it from the objectSid that we hope is here... */
        sidval = ldb_msg_find_ldb_val(local, "objectSid");
 
-       if (!sidval) 
+       if (!sidval)
                return; /* Sorry, no SID today.. */
 
        sid = talloc(remote_mp, struct dom_sid);
        if (sid == NULL) {
                return;
        }
-       status = ndr_pull_struct_blob(sidval, sid, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
-       if (!NT_STATUS_IS_OK(status)) {
+
+       ndr_err = ndr_pull_struct_blob(sidval, sid, NULL, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                talloc_free(sid);
                return;
        }
@@ -119,13 +110,17 @@ static void generate_sambaPrimaryGroupSID(struct ldb_module *module, const char
 
        sidstring = dom_sid_string(remote_mp, sid);
        talloc_free(sid);
-       ldb_msg_add_fmt(module->ldb, remote_mp, "sambaPrimaryGroupSID", "%s-%d", sidstring, ldb_msg_find_uint(local, "primaryGroupID", 0));
+       ldb_msg_add_fmt(remote_mp, "sambaPrimaryGroupSID", "%s-%d", sidstring, ldb_msg_find_attr_as_uint(local, "primaryGroupID", 0));
        talloc_free(sidstring);
 }
 
+/* Just copy the old value. */
 static struct ldb_val convert_uid_samaccount(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
 {
-       return ldb_val_dup(ctx, val);
+       struct ldb_val out = data_blob(NULL, 0);
+       ldb_handler_copy(module->ldb, ctx, val, &out);
+
+       return out;
 }
 
 static struct ldb_val lookup_homedir(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
@@ -157,7 +152,7 @@ static struct ldb_val lookup_gid(struct ldb_module *module, TALLOC_CTX *ctx, con
                return *talloc_zero(ctx, struct ldb_val);
        }
 
-       retval.data = (uint8_t *)talloc_asprintf(ctx, "%d", pwd->pw_gid);
+       retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_gid);
        retval.length = strlen((char *)retval.data);
 
        return retval;
@@ -174,55 +169,91 @@ static struct ldb_val lookup_uid(struct ldb_module *module, TALLOC_CTX *ctx, con
                return *talloc_zero(ctx, struct ldb_val);
        }
 
-       retval.data = (uint8_t *)talloc_asprintf(ctx, "%d", pwd->pw_uid);
+       retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_uid);
        retval.length = strlen((char *)retval.data);
 
        return retval;
 }
 
+/* Encode a sambaSID to an objectSid. */
 static struct ldb_val encode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
 {
-       struct dom_sid *sid = dom_sid_parse_talloc(ctx, (char *)val->data);
-       struct ldb_val *out = talloc_zero(ctx, struct ldb_val);
-       NTSTATUS status;
+       struct ldb_val out = data_blob(NULL, 0);
+       struct dom_sid *sid;
+       enum ndr_err_code ndr_err;
 
+       sid = dom_sid_parse_talloc(ctx, (char *)val->data);
        if (sid == NULL) {
-               return *out;
+               return out;
        }
-       status = ndr_push_struct_blob(out, ctx, sid, 
-                                     (ndr_push_flags_fn_t)ndr_push_dom_sid);
+
+       ndr_err = ndr_push_struct_blob(&out, ctx, 
+                                      NULL,
+                                      sid, (ndr_push_flags_fn_t)ndr_push_dom_sid);
        talloc_free(sid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return *out;
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return out;
        }
 
-       return *out;
+       return out;
 }
 
+/* Decode an objectSid to a sambaSID. */
 static struct ldb_val decode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
 {
+       struct ldb_val out = data_blob(NULL, 0);
        struct dom_sid *sid;
-       NTSTATUS status;
-       struct ldb_val *out = talloc_zero(ctx, struct ldb_val);
-       
+       enum ndr_err_code ndr_err;
+
        sid = talloc(ctx, struct dom_sid);
        if (sid == NULL) {
-               return *out;
+               return out;
        }
-       status = ndr_pull_struct_blob(val, sid, sid, 
-                                     (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
-       if (!NT_STATUS_IS_OK(status)) {
-               talloc_free(sid);
-               return *out;
+
+       ndr_err = ndr_pull_struct_blob(val, sid, NULL, sid,
+                                      (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               goto done;
        }
-       out->data = (uint8_t *)dom_sid_string(ctx, sid);
+
+       out.data = (uint8_t *)dom_sid_string(ctx, sid);
+       if (out.data == NULL) {
+               goto done;
+       }
+       out.length = strlen((const char *)out.data);
+
+done:
        talloc_free(sid);
-       if (out->data == NULL) {
-               return *out;
+       return out;
+}
+
+/* Convert 16 bytes to 32 hex digits. */
+static struct ldb_val bin2hex(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
+{
+       struct ldb_val out;
+       struct samr_Password pwd;
+       if (val->length != sizeof(pwd.hash)) {
+               return data_blob(NULL, 0);
        }
-       out->length = strlen((const char *)out->data);
+       memcpy(pwd.hash, val->data, sizeof(pwd.hash));
+       out = data_blob_string_const(smbpasswd_sethexpwd(ctx, &pwd, 0));
+       if (!out.data) {
+               return data_blob(NULL, 0);
+       }
+       return out;
+}
 
-       return *out;
+/* Convert 32 hex digits to 16 bytes. */
+static struct ldb_val hex2bin(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
+{
+       struct ldb_val out;
+       struct samr_Password *pwd;
+       pwd = smbpasswd_gethexpwd(ctx, (const char *)val->data);
+       if (!pwd) {
+               return data_blob(NULL, 0);
+       }
+       out = data_blob_talloc(ctx, pwd->hash, sizeof(pwd->hash));
+       return out;
 }
 
 const struct ldb_map_objectclass samba3_objectclasses[] = {
@@ -240,15 +271,15 @@ const struct ldb_map_objectclass samba3_objectclasses[] = {
                .musts = { "cn", "gidNumber", NULL },
                .mays = { "userPassword", "memberUid", "description", NULL },
        },
-       { 
-               .local_name = "group", 
+       {
+               .local_name = "group",
                .remote_name = "sambaGroupMapping",
                .base_classes = { "top", "posixGroup", NULL },
                .musts = { "gidNumber", "sambaSID", "sambaGroupType", NULL },
                .mays = { "displayName", "description", "sambaSIDList", NULL },
        },
-       { 
-               .local_name = "user", 
+       {
+               .local_name = "user",
                .remote_name = "sambaSAMAccount",
                .base_classes = { "top", "posixAccount", NULL },
                .musts = { "uid", "sambaSID", NULL },
@@ -259,11 +290,11 @@ const struct ldb_map_objectclass samba3_objectclasses[] = {
                        "sambaLogonScript", "sambaProfilePath", "description", "sambaUserWorkstations",
                        "sambaPrimaryGroupSID", "sambaDomainName", "sambaMungedDial",
                        "sambaBadPasswordCount", "sambaBadPasswordTime",
-               "sambaPasswordHistory", "sambaLogonHours", NULL }
-       
+               "sambaPasswordHistory", "sambaLogonHours", NULL }
+
        },
-       { 
-               .local_name = "domain", 
+       {
+               .local_name = "domain",
                .remote_name = "sambaDomain",
                .base_classes = { "top", NULL },
                .musts = { "sambaDomainName", "sambaSID", NULL },
@@ -272,7 +303,7 @@ const struct ldb_map_objectclass samba3_objectclasses[] = {
                { NULL, NULL }
 };
 
-const struct ldb_map_attribute samba3_attributes[] = 
+const struct ldb_map_attribute samba3_attributes[] =
 {
        /* sambaNextRid -> nextRid */
        {
@@ -298,11 +329,13 @@ const struct ldb_map_attribute samba3_attributes[] =
 
        /* sambaLMPassword -> lmPwdHash*/
        {
-               .local_name = "lmPwdHash",
-               .type = MAP_RENAME,
+               .local_name = "dBCSPwd",
+               .type = MAP_CONVERT,
                .u = {
-                       .rename = {
+                       .convert = {
                                .remote_name = "sambaLMPassword",
+                               .convert_local = bin2hex,
+                               .convert_remote = hex2bin,
                        },
                },
        },
@@ -320,11 +353,13 @@ const struct ldb_map_attribute samba3_attributes[] =
 
        /* sambaNTPassword -> ntPwdHash*/
        {
-               .local_name = "ntPwdHash",
-               .type = MAP_RENAME,
+               .local_name = "ntpwdhash",
+               .type = MAP_CONVERT,
                .u = {
-                       .rename = {
+                       .convert = {
                                .remote_name = "sambaNTPassword",
+                               .convert_local = bin2hex,
+                               .convert_remote = hex2bin,
                        },
                },
        },
@@ -337,7 +372,7 @@ const struct ldb_map_attribute samba3_attributes[] =
                        .generate = {
                                .remote_names = { "sambaPrimaryGroupSID", NULL },
                                .generate_local = generate_primaryGroupID,
-                               .generate_remote = generate_sambaPrimaryGroupSID, 
+                               .generate_remote = generate_sambaPrimaryGroupSID,
                        },
                },
        },
@@ -434,7 +469,7 @@ const struct ldb_map_attribute samba3_attributes[] =
        },
 
        /* codePage */
-       { 
+       {
                .local_name = "codePage",
                .type = MAP_IGNORE,
        },
@@ -465,13 +500,13 @@ const struct ldb_map_attribute samba3_attributes[] =
        },
 
        /* nTMixedDomain */
-       { 
+       {
                .local_name = "nTMixedDomain",
                .type = MAP_IGNORE,
        },
 
        /* operatingSystem */
-       { 
+       {
                .local_name = "operatingSystem",
                .type = MAP_IGNORE,
        },
@@ -531,7 +566,7 @@ const struct ldb_map_attribute samba3_attributes[] =
                .type = MAP_CONVERT,
                .u = {
                        .convert = {
-                               .remote_name = "sambaSID", 
+                               .remote_name = "sambaSID",
                                .convert_local = decode_sid,
                                .convert_remote = encode_sid,
                        },
@@ -547,11 +582,11 @@ const struct ldb_map_attribute samba3_attributes[] =
                                .remote_name = "sambaPwdLastSet",
                        },
                },
-       },      
+       },
 
        /* accountExpires */
        {
-               .local_name = "accountExpires", 
+               .local_name = "accountExpires",
                .type = MAP_IGNORE,
        },
 
@@ -572,55 +607,55 @@ const struct ldb_map_attribute samba3_attributes[] =
                .local_name = "createTimestamp",
                .type = MAP_IGNORE,
        },
-       
+
        /* creationTime */
        {
                .local_name = "creationTime",
                .type = MAP_IGNORE,
        },
-       
+
        /* dMDLocation */
        {
                .local_name = "dMDLocation",
                .type = MAP_IGNORE,
        },
-       
+
        /* fSMORoleOwner */
        {
                .local_name = "fSMORoleOwner",
                .type = MAP_IGNORE,
        },
-       
+
        /* forceLogoff */
        {
                .local_name = "forceLogoff",
                .type = MAP_IGNORE,
        },
-       
+
        /* instanceType */
        {
                .local_name = "instanceType",
                .type = MAP_IGNORE,
        },
-       
+
        /* invocationId */
        {
                .local_name = "invocationId",
                .type = MAP_IGNORE,
        },
-       
+
        /* isCriticalSystemObject */
        {
                .local_name = "isCriticalSystemObject",
                .type = MAP_IGNORE,
        },
-       
+
        /* localPolicyFlags */
        {
                .local_name = "localPolicyFlags",
                .type = MAP_IGNORE,
        },
-       
+
        /* lockOutObservationWindow */
        {
                .local_name = "lockOutObservationWindow",
@@ -813,9 +848,9 @@ const struct ldb_map_attribute samba3_attributes[] =
                .type = MAP_IGNORE,
        },
 
-       /* unicodePwd */
+       /* sambaPassword */
        {
-               .local_name = "unicodePwd",
+               .local_name = "sambaPassword",
                .type = MAP_IGNORE,
        },
 
@@ -873,30 +908,38 @@ const struct ldb_map_attribute samba3_attributes[] =
                        },
                },
        },
-       
-       /* unicodePwd */
-       {
-               .local_name = "unicodePwd",
-               .type = MAP_GENERATE,
-               .u = {
-                       .generate = {
-                               .remote_names = { "sambaNTPassword", "sambaLMPassword", NULL },
-                               .generate_local = NULL,
-                               .generate_remote = generate_hashes
-                       },
-               },
-       },
        {
                .local_name = NULL,
        }
 };
 
-       /* the init function */
-#ifdef HAVE_DLOPEN_DISABLED
-struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
-#else
-struct ldb_module *ldb_samba3sam_module_init(struct ldb_context *ldb, const char *options[])
-#endif
+/* the context init function */
+static int samba3sam_init(struct ldb_module *module)
+{
+       int ret;
+
+       ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, NULL, "samba3sam");
+       if (ret != LDB_SUCCESS)
+               return ret;
+
+       return ldb_next_init(module);
+}
+
+static struct ldb_module_ops samba3sam_ops = {
+       .name              = "samba3sam",
+       .init_context      = samba3sam_init,
+};
+
+/* the init function */
+int ldb_samba3sam_module_init(void)
 {
-       return ldb_map_init(ldb, samba3_attributes, samba3_objectclasses, "samba3sam");
+       struct ldb_module_ops ops = ldb_map_get_ops();
+       samba3sam_ops.add       = ops.add;
+       samba3sam_ops.modify    = ops.modify;
+       samba3sam_ops.del       = ops.del;
+       samba3sam_ops.rename    = ops.rename;
+       samba3sam_ops.search    = ops.search;
+       samba3sam_ops.wait      = ops.wait;
+
+       return ldb_register_module(&samba3sam_ops);
 }