summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2008-09-23 11:15:46 -0700
committerAndrew Tridgell <tridge@samba.org>2008-09-23 11:15:46 -0700
commit66092ced5e1dc4d35923a3c90bcb3214a885b17d (patch)
treed40fd46e86244f1b45abda2a95c8fe84bfc88c3c /source3
parent9cf29abee296ea2fcdf712687a6ce2cf9fd9d74c (diff)
parent353aaf26c5f71d9a94e799a1c1e37449211e7a87 (diff)
downloadsamba-66092ced5e1dc4d35923a3c90bcb3214a885b17d.tar.gz
samba-66092ced5e1dc4d35923a3c90bcb3214a885b17d.tar.bz2
samba-66092ced5e1dc4d35923a3c90bcb3214a885b17d.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in19
-rw-r--r--source3/client/mount.cifs.c10
-rw-r--r--source3/configure.in5
-rw-r--r--source3/include/charset.h2
-rw-r--r--source3/include/proto.h32
-rw-r--r--source3/lib/messages_local.c4
-rw-r--r--source3/lib/netapi/examples/user/user_modalsset.c1
-rw-r--r--source3/lib/netapi/tests/Makefile.in2
-rw-r--r--source3/lib/netapi/tests/common.h2
-rw-r--r--source3/lib/netapi/tests/netapitest.c5
-rw-r--r--source3/lib/netapi/tests/netfile.c143
-rw-r--r--source3/lib/secdesc.c4
-rw-r--r--source3/libads/authdata.c14
-rw-r--r--source3/libads/cldap.c2
-rw-r--r--source3/libcli/nbt/libnbt.h353
-rw-r--r--source3/libcli/nbt/nbtname.c626
-rw-r--r--source3/libnet/libnet_dssync_keytab.c6
-rw-r--r--source3/libnet/libnet_samsync.c4
-rw-r--r--source3/librpc/gen_ndr/libnetapi.h2
-rw-r--r--source3/librpc/gen_ndr/nbt.h2
-rw-r--r--source3/librpc/gen_ndr/ndr_libnetapi.c6
-rw-r--r--source3/librpc/gen_ndr/ndr_nbt.c12
-rw-r--r--source3/librpc/gen_ndr/ndr_nbt.h8
-rw-r--r--source3/librpc/idl/libnetapi.idl2
-rw-r--r--source3/librpc/idl/nbt.idl8
-rw-r--r--source3/librpc/ndr/ndr.c14
-rw-r--r--source3/libsmb/clidgram.c2
-rw-r--r--source3/libsmb/clientgen.c4
-rw-r--r--source3/libsmb/dsgetdcname.c4
-rw-r--r--source3/libsmb/samlogon_cache.c4
-rw-r--r--source3/libsmb/trusts_util.c108
-rw-r--r--source3/modules/vfs_acl_xattr.c4
-rw-r--r--source3/modules/vfs_xattr_tdb.c4
-rw-r--r--source3/rpc_client/cli_netlogon.c91
-rw-r--r--source3/rpc_client/init_netlogon.c17
-rw-r--r--source3/samba4.m41
-rw-r--r--source3/samba4.mk5
-rwxr-xr-xsource3/script/build_idl.sh2
-rw-r--r--source3/smbd/notify_internal.c8
-rw-r--r--source3/utils/net_rpc_registry.c2
-rw-r--r--source3/winbindd/idmap_adex/cell_util.c292
-rw-r--r--source3/winbindd/idmap_adex/domain_util.c278
-rw-r--r--source3/winbindd/idmap_adex/gc_util.c848
-rw-r--r--source3/winbindd/idmap_adex/idmap_adex.c460
-rw-r--r--source3/winbindd/idmap_adex/idmap_adex.h257
-rw-r--r--source3/winbindd/idmap_adex/likewise_cell.c425
-rw-r--r--source3/winbindd/idmap_adex/provider_unified.c1180
-rw-r--r--source3/winbindd/winbindd_ads.c20
-rw-r--r--source3/winbindd/winbindd_async.c2
-rw-r--r--source3/winbindd/winbindd_group.c8
-rw-r--r--source3/winbindd/winbindd_pam.c2
-rw-r--r--source3/winbindd/winbindd_proto.h4
-rw-r--r--source3/winbindd/winbindd_rpc.c5
-rw-r--r--source3/winbindd/winbindd_util.c29
54 files changed, 4176 insertions, 1178 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 2300e4a20c..94d8d50da8 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -376,7 +376,7 @@ LIBADS_SERVER_OBJ = libads/kerberos_verify.o libads/authdata.o \
SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o
-LIBNBT_OBJ = libcli/nbt/nbtname.o \
+LIBNBT_OBJ = ../libcli/nbt/nbtname.o \
librpc/gen_ndr/ndr_nbt.o \
librpc/gen_ndr/ndr_svcctl.o
@@ -946,13 +946,14 @@ SHARESEC_OBJ = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
$(LIBSAMBA_OBJ) \
$(POPT_LIB_OBJ)
-TALLOCTORT_OBJ = @tallocdir@/testsuite.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
- $(LIBSAMBA_OBJ)
+TALLOCTORT_OBJ = @tallocdir@/testsuite.o @tallocdir@/testsuite_main.o \
+ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSAMBA_OBJ)
REPLACETORT_OBJ = @libreplacedir@/test/testsuite.o \
@libreplacedir@/test/getifaddrs.o \
@libreplacedir@/test/os2_delete.o \
@libreplacedir@/test/strptime.o \
+ @libreplacedir@/test/main.o \
$(LIBREPLACE_OBJ)
NDRDUMP_OBJ = librpc/tools/ndrdump.o \
@@ -984,6 +985,14 @@ IDMAP_HASH_OBJ = \
winbindd/idmap_hash/idmap_hash.o \
winbindd/idmap_hash/mapfile.o
+IDMAP_ADEX_OBJ = \
+ winbindd/idmap_adex/idmap_adex.o \
+ winbindd/idmap_adex/cell_util.o \
+ winbindd/idmap_adex/likewise_cell.o \
+ winbindd/idmap_adex/provider_unified.o \
+ winbindd/idmap_adex/gc_util.o \
+ winbindd/idmap_adex/domain_util.o
+
WINBINDD_OBJ1 = \
winbindd/winbindd.o \
winbindd/winbindd_user.o \
@@ -2217,6 +2226,10 @@ bin/hash.@SHLIBEXT@: $(BINARY_PREREQS) $(IDMAP_HASH_OBJ)
@echo "Building plugin $@"
@$(SHLD_MODULE) $(IDMAP_HASH_OBJ)
+bin/adex.@SHLIBEXT@: $(BINARY_PREREQS) $(IDMAP_ADEX_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD_MODULE) $(IDMAP_ADEX_OBJ)
+
bin/tdb2.@SHLIBEXT@: $(BINARY_PREREQS) winbindd/idmap_tdb2.o
@echo "Building plugin $@"
@$(SHLD_MODULE) winbindd/idmap_tdb2.o
diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c
index 3b56e5f861..b7a76c6102 100644
--- a/source3/client/mount.cifs.c
+++ b/source3/client/mount.cifs.c
@@ -56,6 +56,10 @@
#endif /* _SAMBA_BUILD_ */
#endif /* MOUNT_CIFS_VENDOR_SUFFIX */
+#ifdef _SAMBA_BUILD_
+#include "include/config.h"
+#endif
+
#ifndef MS_MOVE
#define MS_MOVE 8192
#endif
@@ -94,6 +98,8 @@ char * prefixpath = NULL;
/* like strncpy but does not 0 fill the buffer and always null
* terminates. bufsize is the size of the destination buffer */
+
+#ifndef HAVE_STRLCPY
static size_t strlcpy(char *d, const char *s, size_t bufsize)
{
size_t len = strlen(s);
@@ -104,10 +110,13 @@ static size_t strlcpy(char *d, const char *s, size_t bufsize)
d[len] = 0;
return ret;
}
+#endif
/* like strncat but does not 0 fill the buffer and always null
* terminates. bufsize is the length of the buffer, which should
* be one more than the maximum resulting string length */
+
+#ifndef HAVE_STRLCAT
static size_t strlcat(char *d, const char *s, size_t bufsize)
{
size_t len1 = strlen(d);
@@ -126,6 +135,7 @@ static size_t strlcat(char *d, const char *s, size_t bufsize)
}
return ret;
}
+#endif
/* BB finish BB
diff --git a/source3/configure.in b/source3/configure.in
index 640afc47fb..f23f6b55be 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -6058,6 +6058,7 @@ SMB_MODULE(idmap_nss, winbindd/idmap_nss.o, "bin/nss.$SHLIBEXT", IDMAP)
SMB_MODULE(idmap_rid, winbindd/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP)
SMB_MODULE(idmap_ad, winbindd/idmap_ad.o, "bin/ad.$SHLIBEXT", IDMAP)
SMB_MODULE(idmap_hash, \$(IDMAP_HASH_OBJ), "bin/hash.$SHLIBEXT", IDMAP)
+SMB_MODULE(idmap_adex, \$(IDMAP_ADEX_OBJ), "bin/adex.$SHLIBEXT", IDMAP)
SMB_SUBSYSTEM(IDMAP, winbindd/idmap.o)
SMB_MODULE(nss_info_template, winbindd/nss_info_template.o, "bin/template.$SHLIBEXT", NSS_INFO)
@@ -6271,8 +6272,10 @@ fi
SMBD_LIBS="$samba_dmapi_libs"
AC_SUBST(SMBD_LIBS)
+CFLAGS="${CFLAGS} \$(FLAGS)"
+
if test x$MERGED_BUILD != x1; then
- CFLAGS="${CFLAGS} \$(FLAGS) -D_SAMBA_BUILD_=3"
+ CFLAGS="${CFLAGS} -D_SAMBA_BUILD_=3"
fi
AC_OUTPUT(Makefile
diff --git a/source3/include/charset.h b/source3/include/charset.h
index 4d04b5a1a6..1c2a5fb5f0 100644
--- a/source3/include/charset.h
+++ b/source3/include/charset.h
@@ -18,6 +18,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+struct smb_iconv_convenience;
+
/* this defines the charset types used in samba */
typedef enum {CH_UTF16LE=0, CH_UTF16=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4, CH_UTF16BE=5} charset_t;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 2901911c70..a2772384c5 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2204,23 +2204,6 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
char **returned_principal);
-/* The following definitions come from libcli/nbt/nbtname.c */
-
-_PUBLIC_ void ndr_print_nbt_string(struct ndr_print *ndr, const char *name, const char *s);
-_PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_flags, const char **s);
-_PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s);
-_PUBLIC_ enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r);
-_PUBLIC_ enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r);
-_PUBLIC_ NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname);
-_PUBLIC_ NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct nbt_name *name);
-_PUBLIC_ NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name);
-_PUBLIC_ void nbt_choose_called_name(TALLOC_CTX *mem_ctx,
- struct nbt_name *n, const char *name, int type);
-_PUBLIC_ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name);
-_PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, const struct nbt_name **_r);
-_PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r);
-_PUBLIC_ void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r);
-
/* The following definitions come from libgpo/gpext/gpext.c */
struct gp_extension *get_gp_extension_list(void);
@@ -3960,16 +3943,14 @@ _PUBLIC_ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, con
_PUBLIC_ uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p);
_PUBLIC_ uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p);
_PUBLIC_ uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p);
-_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
- ndr_pull_flags_fn_t fn);
+_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, void *p, ndr_pull_flags_fn_t fn);
_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
ndr_pull_flags_fn_t fn);
_PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
uint32_t level, ndr_pull_flags_fn_t fn);
_PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
uint32_t level, ndr_pull_flags_fn_t fn);
-_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p,
- ndr_push_flags_fn_t fn);
+_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, const void *p, ndr_push_flags_fn_t fn);
_PUBLIC_ enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
uint32_t level, ndr_push_flags_fn_t fn);
_PUBLIC_ size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push);
@@ -7049,6 +7030,12 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
DATA_BLOB lm_response,
DATA_BLOB nt_response,
struct netr_SamInfo3 **info3);
+NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ const unsigned char orig_trust_passwd_hash[16],
+ const char *new_trust_pwd_cleartext,
+ const unsigned char new_trust_passwd_hash[16],
+ uint32_t sec_channel_type);
/* The following definitions come from rpc_client/cli_pipe.c */
@@ -7427,6 +7414,9 @@ void init_netr_PasswordInfo(struct netr_PasswordInfo *r,
const char *workstation,
struct samr_Password lmpassword,
struct samr_Password ntpassword);
+void init_netr_CryptPassword(const char *pwd,
+ unsigned char session_key[16],
+ struct netr_CryptPassword *pwd_buf);
/* The following definitions come from rpc_client/init_samr.c */
diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c
index f436afc2ff..9f7f88f783 100644
--- a/source3/lib/messages_local.c
+++ b/source3/lib/messages_local.c
@@ -160,7 +160,7 @@ static NTSTATUS messaging_tdb_fetch(TDB_CONTEXT *msg_tdb,
blob = data_blob_const(data.dptr, data.dsize);
ndr_err = ndr_pull_struct_blob(
- &blob, result, result,
+ &blob, result, NULL, result,
(ndr_pull_flags_fn_t)ndr_pull_messaging_array);
SAFE_FREE(data.dptr);
@@ -203,7 +203,7 @@ static NTSTATUS messaging_tdb_store(TDB_CONTEXT *msg_tdb,
}
ndr_err = ndr_push_struct_blob(
- &blob, mem_ctx, array,
+ &blob, mem_ctx, NULL, array,
(ndr_push_flags_fn_t)ndr_push_messaging_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
diff --git a/source3/lib/netapi/examples/user/user_modalsset.c b/source3/lib/netapi/examples/user/user_modalsset.c
index 57e1ef70ea..c6958a9012 100644
--- a/source3/lib/netapi/examples/user/user_modalsset.c
+++ b/source3/lib/netapi/examples/user/user_modalsset.c
@@ -95,6 +95,7 @@ int main(int argc, const char **argv)
case 1:
case 2:
case 3:
+ break;
case 1001:
u1001.usrmod1001_min_passwd_len = 0;
buffer = (uint8_t *)&u1001;
diff --git a/source3/lib/netapi/tests/Makefile.in b/source3/lib/netapi/tests/Makefile.in
index 0145753212..659f82c9d8 100644
--- a/source3/lib/netapi/tests/Makefile.in
+++ b/source3/lib/netapi/tests/Makefile.in
@@ -44,7 +44,7 @@ bin/.dummy:
CMDLINE_OBJ = common.o
NETAPIBUFFER_OBJ = netapibuffer.o
-NETAPITEST_OBJ = netapitest.o netlocalgroup.o netuser.o netgroup.o netdisplay.o netshare.o $(CMDLINE_OBJ)
+NETAPITEST_OBJ = netapitest.o netlocalgroup.o netuser.o netgroup.o netdisplay.o netshare.o netfile.o $(CMDLINE_OBJ)
bin/netapitest@EXEEXT@: $(BINARY_PREREQS) $(NETAPITEST_OBJ)
@echo Linking $@
diff --git a/source3/lib/netapi/tests/common.h b/source3/lib/netapi/tests/common.h
index 5a320321ba..9320840909 100644
--- a/source3/lib/netapi/tests/common.h
+++ b/source3/lib/netapi/tests/common.h
@@ -41,6 +41,8 @@ NET_API_STATUS netapitest_display(struct libnetapi_ctx *ctx,
const char *hostname);
NET_API_STATUS netapitest_share(struct libnetapi_ctx *ctx,
const char *hostname);
+NET_API_STATUS netapitest_file(struct libnetapi_ctx *ctx,
+ const char *hostname);
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
diff --git a/source3/lib/netapi/tests/netapitest.c b/source3/lib/netapi/tests/netapitest.c
index 87144020f5..4a38f721d8 100644
--- a/source3/lib/netapi/tests/netapitest.c
+++ b/source3/lib/netapi/tests/netapitest.c
@@ -84,6 +84,11 @@ int main(int argc, const char **argv)
goto out;
}
+ status = netapitest_file(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
out:
if (status != 0) {
printf("testsuite failed with: %s\n",
diff --git a/source3/lib/netapi/tests/netfile.c b/source3/lib/netapi/tests/netfile.c
new file mode 100644
index 0000000000..36ee8288ee
--- /dev/null
+++ b/source3/lib/netapi/tests/netfile.c
@@ -0,0 +1,143 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetFile testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netfileenum(const char *hostname,
+ uint32_t level)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct FILE_INFO_2 *i2;
+ struct FILE_INFO_3 *i3;
+
+ printf("testing NetFileEnum level %d\n", level);
+
+ do {
+ status = NetFileEnum(hostname,
+ NULL,
+ NULL,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 2:
+ i2 = (struct FILE_INFO_2 *)buffer;
+ break;
+ case 3:
+ i3 = (struct FILE_INFO_3 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 2:
+ case 3:
+ break;
+ default:
+ break;
+ }
+
+ switch (level) {
+ case 2:
+ i2++;
+ break;
+ case 3:
+ i3++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_file(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ uint8_t *buffer = NULL;
+ uint32_t levels[] = { 2, 3 };
+ uint32_t enum_levels[] = { 2, 3 };
+ int i;
+
+ printf("NetFile tests\n");
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netfileenum(hostname, enum_levels[i]);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetFileEnum");
+ goto out;
+ }
+ }
+
+ /* basic queries */
+#if 0
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetFileGetInfo level %d\n", levels[i]);
+
+ status = NetFileGetInfo(hostname, fid, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetFileGetInfo");
+ goto out;
+ }
+ }
+#endif
+
+ status = 0;
+
+ printf("NetFile tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetFile testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c
index 44ae23271e..4965200bc1 100644
--- a/source3/lib/secdesc.c
+++ b/source3/lib/secdesc.c
@@ -249,7 +249,7 @@ NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
enum ndr_err_code ndr_err;
ndr_err = ndr_push_struct_blob(
- &blob, mem_ctx, secdesc,
+ &blob, mem_ctx, NULL, secdesc,
(ndr_push_flags_fn_t)ndr_push_security_descriptor);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -285,7 +285,7 @@ NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
blob = data_blob_const(data, len);
ndr_err = ndr_pull_struct_blob(
- &blob, result, result,
+ &blob, result, NULL, result,
(ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c
index 0bde3e6984..40f051c851 100644
--- a/source3/libads/authdata.c
+++ b/source3/libads/authdata.c
@@ -108,7 +108,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
}
ndr_err = ndr_pull_struct_blob(pac_data_blob, pac_data,
- pac_data,
+ NULL, pac_data,
(ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
@@ -124,7 +124,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
}
ndr_err = ndr_pull_struct_blob(pac_data_blob, pac_data_raw,
- pac_data_raw,
+ NULL, pac_data_raw,
(ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
@@ -205,7 +205,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
/* We find the data blobs above, now we parse them to get at the exact portion we should zero */
ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe,
- kdc_sig_wipe,
+ NULL, kdc_sig_wipe,
(ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
@@ -215,7 +215,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
}
ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe,
- srv_sig_wipe,
+ NULL, srv_sig_wipe,
(ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
@@ -230,7 +230,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
/* and reencode, back into the same place it came from */
ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw,
- kdc_sig_wipe,
+ NULL, kdc_sig_wipe,
(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
@@ -239,7 +239,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
return status;
}
ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw,
- srv_sig_wipe,
+ NULL, srv_sig_wipe,
(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
@@ -250,7 +250,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
/* push out the whole structure, but now with zero'ed signatures */
ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw,
- pac_data_raw,
+ NULL, pac_data_raw,
(ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
diff --git a/source3/libads/cldap.c b/source3/libads/cldap.c
index 11565065af..73b28b523a 100644
--- a/source3/libads/cldap.c
+++ b/source3/libads/cldap.c
@@ -294,7 +294,7 @@ bool pull_mailslot_cldap_reply(TALLOC_CTX *mem_ctx,
uint32_t nt_version_query = ((*nt_version) & 0x0000001f);
uint16_t command = 0;
- ndr_err = ndr_pull_struct_blob(blob, mem_ctx, &command,
+ ndr_err = ndr_pull_struct_blob(blob, mem_ctx, NULL, &command,
(ndr_pull_flags_fn_t)ndr_pull_uint16);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return false;
diff --git a/source3/libcli/nbt/libnbt.h b/source3/libcli/nbt/libnbt.h
deleted file mode 100644
index d37a17c192..0000000000
--- a/source3/libcli/nbt/libnbt.h
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- a raw async NBT library
-
- 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 3 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, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __LIBNBT_H__
-#define __LIBNBT_H__
-
-#include "librpc/gen_ndr/nbt.h"
-#include "librpc/ndr/libndr.h"
-
-/*
- possible states for pending requests
-*/
-enum nbt_request_state {NBT_REQUEST_SEND,
- NBT_REQUEST_WAIT,
- NBT_REQUEST_DONE,
- NBT_REQUEST_TIMEOUT,
- NBT_REQUEST_ERROR};
-
-/*
- a nbt name request
-*/
-struct nbt_name_request {
- struct nbt_name_request *next, *prev;
-
- enum nbt_request_state state;
-
- NTSTATUS status;
-
- /* the socket this was on */
- struct nbt_name_socket *nbtsock;
-
- /* where to send the request */
- struct socket_address *dest;
-
- /* timeout between retries */
- int timeout;
-
- /* how many retries to send on timeout */
- int num_retries;
-
- /* whether we have received a WACK */
- bool received_wack;
-
- /* the timeout event */
- struct timed_event *te;
-
- /* the name transaction id */
- uint16_t name_trn_id;
-
- /* is it a reply? */
- bool is_reply;
-
- /* the encoded request */
- DATA_BLOB encoded;
-
- /* shall we allow multiple replies? */
- bool allow_multiple_replies;
-
- unsigned int num_replies;
- struct nbt_name_reply {
- struct nbt_name_packet *packet;
- struct socket_address *dest;
- } *replies;
-
- /* information on what to do on completion */
- struct {
- void (*fn)(struct nbt_name_request *);
- void *_private;
- } async;
-};
-
-
-
-/*
- context structure for operations on name queries
-*/
-struct nbt_name_socket {
- struct socket_context *sock;
- struct event_context *event_ctx;
-/*
- struct smb_iconv_convenience *iconv_convenience;
-*/
- /* a queue of requests pending to be sent */
- struct nbt_name_request *send_queue;
-
- /* the fd event */
- struct fd_event *fde;
-
- /* mapping from name_trn_id to pending event */
- struct idr_context *idr;
-
- /* how many requests are waiting for a reply */
- uint16_t num_pending;
-
- /* what to do with incoming request packets */
- struct {
- void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *,
- struct socket_address *);
- void *_private;
- } incoming;
-
- /* what to do with unexpected replies */
- struct {
- void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *,
- struct socket_address *);
- void *_private;
- } unexpected;
-};
-
-
-/* a simple name query */
-struct nbt_name_query {
- struct {
- struct nbt_name name;
- const char *dest_addr;
- uint16_t dest_port;
- bool broadcast;
- bool wins_lookup;
- int timeout; /* in seconds */
- int retries;
- } in;
- struct {
- const char *reply_from;
- struct nbt_name name;
- int16_t num_addrs;
- const char **reply_addrs;
- } out;
-};
-
-/* a simple name status query */
-struct nbt_name_status {
- struct {
- struct nbt_name name;
- const char *dest_addr;
- uint16_t dest_port;
- int timeout; /* in seconds */
- int retries;
- } in;
- struct {
- const char *reply_from;
- struct nbt_name name;
- struct nbt_rdata_status status;
- } out;
-};
-
-/* a name registration request */
-struct nbt_name_register {
- struct {
- struct nbt_name name;
- const char *dest_addr;
- uint16_t dest_port;
- const char *address;
- uint16_t nb_flags;
- bool register_demand;
- bool broadcast;
- bool multi_homed;
- uint32_t ttl;
- int timeout; /* in seconds */
- int retries;
- } in;
- struct {
- const char *reply_from;
- struct nbt_name name;
- const char *reply_addr;
- uint8_t rcode;
- } out;
-};
-
-/* a send 3 times then demand name broadcast name registration */
-struct nbt_name_register_bcast {
- struct {
- struct nbt_name name;
- const char *dest_addr;
- uint16_t dest_port;
- const char *address;
- uint16_t nb_flags;
- uint32_t ttl;
- } in;
-};
-
-
-/* wins name register with multiple wins servers to try and multiple
- addresses to register */
-struct nbt_name_register_wins {
- struct {
- struct nbt_name name;
- const char **wins_servers;
- uint16_t wins_port;
- const char **addresses;
- uint16_t nb_flags;
- uint32_t ttl;
- } in;
- struct {
- const char *wins_server;
- uint8_t rcode;
- } out;
-};
-
-
-
-/* a name refresh request */
-struct nbt_name_refresh {
- struct {
- struct nbt_name name;
- const char *dest_addr;
- uint16_t dest_port;
- const char *address;
- uint16_t nb_flags;
- bool broadcast;
- uint32_t ttl;
- int timeout; /* in seconds */
- int retries;
- } in;
- struct {
- const char *reply_from;
- struct nbt_name name;
- const char *reply_addr;
- uint8_t rcode;
- } out;
-};
-
-/* wins name refresh with multiple wins servers to try and multiple
- addresses to register */
-struct nbt_name_refresh_wins {
- struct {
- struct nbt_name name;
- const char **wins_servers;
- uint16_t wins_port;
- const char **addresses;
- uint16_t nb_flags;
- uint32_t ttl;
- } in;
- struct {
- const char *wins_server;
- uint8_t rcode;
- } out;
-};
-
-
-/* a name release request */
-struct nbt_name_release {
- struct {
- struct nbt_name name;
- const char *dest_addr;
- uint16_t dest_port;
- const char *address;
- uint16_t nb_flags;
- bool broadcast;
- int timeout; /* in seconds */
- int retries;
- } in;
- struct {
- const char *reply_from;
- struct nbt_name name;
- const char *reply_addr;
- uint8_t rcode;
- } out;
-};
-
-struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx,
- struct event_context *event_ctx);
- /*,
- struct smb_iconv_convenience *iconv_convenience);*/
-struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock,
- struct nbt_name_query *io);
-NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
- TALLOC_CTX *mem_ctx, struct nbt_name_query *io);
-NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock,
- TALLOC_CTX *mem_ctx, struct nbt_name_query *io);
-struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *nbtsock,
- struct nbt_name_status *io);
-NTSTATUS nbt_name_status_recv(struct nbt_name_request *req,
- TALLOC_CTX *mem_ctx, struct nbt_name_status *io);
-NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock,
- TALLOC_CTX *mem_ctx, struct nbt_name_status *io);
-
-NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname);
-NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct nbt_name *name);
-NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name);
-void nbt_choose_called_name(TALLOC_CTX *mem_ctx, struct nbt_name *n, const char *name, int type);
-char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name);
-NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock,
- TALLOC_CTX *mem_ctx, struct nbt_name_register *io);
-NTSTATUS nbt_name_refresh(struct nbt_name_socket *nbtsock,
- TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io);
-NTSTATUS nbt_name_release(struct nbt_name_socket *nbtsock,
- TALLOC_CTX *mem_ctx, struct nbt_name_release *io);
-NTSTATUS nbt_name_register_wins(struct nbt_name_socket *nbtsock,
- TALLOC_CTX *mem_ctx,
- struct nbt_name_register_wins *io);
-NTSTATUS nbt_name_refresh_wins(struct nbt_name_socket *nbtsock,
- TALLOC_CTX *mem_ctx,
- struct nbt_name_refresh_wins *io);
-NTSTATUS nbt_name_register_recv(struct nbt_name_request *req,
- TALLOC_CTX *mem_ctx, struct nbt_name_register *io);
-struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock,
- struct nbt_name_register *io);
-NTSTATUS nbt_name_release_recv(struct nbt_name_request *req,
- TALLOC_CTX *mem_ctx, struct nbt_name_release *io);
-
-struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket *nbtsock,
- struct nbt_name_release *io);
-
-NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req,
- TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io);
-
-NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock,
- void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *,
- struct socket_address *),
- void *_private);
-NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock,
- struct socket_address *dest,
- struct nbt_name_packet *request);
-
-
-NDR_SCALAR_PROTO(wrepl_nbt_name, const struct nbt_name *);
-NDR_SCALAR_PROTO(nbt_string, const char *);
-NDR_BUFFER_PROTO(nbt_name, struct nbt_name);
-NTSTATUS nbt_rcode_to_ntstatus(uint8_t rcode);
-
-struct composite_context;
-struct composite_context *nbt_name_register_bcast_send(struct nbt_name_socket *nbtsock,
- struct nbt_name_register_bcast *io);
-NTSTATUS nbt_name_register_bcast_recv(struct composite_context *c);
-struct composite_context *nbt_name_register_wins_send(struct nbt_name_socket *nbtsock,
- struct nbt_name_register_wins *io);
-NTSTATUS nbt_name_refresh_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
- struct nbt_name_refresh_wins *io);
-struct composite_context *nbt_name_refresh_wins_send(struct nbt_name_socket *nbtsock,
- struct nbt_name_refresh_wins *io);
-NTSTATUS nbt_name_register_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
- struct nbt_name_register_wins *io);
-
-
-#endif /* __LIBNBT_H__ */
diff --git a/source3/libcli/nbt/nbtname.c b/source3/libcli/nbt/nbtname.c
deleted file mode 100644
index fbb9550655..0000000000
--- a/source3/libcli/nbt/nbtname.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- manipulate nbt name structures
-
- 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 3 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, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- see rfc1002 for the detailed format of compressed names
-*/
-
-#include "includes.h"
-#include "librpc/gen_ndr/ndr_nbt.h"
-#include "librpc/gen_ndr/ndr_misc.h"
-
-/* don't allow an unlimited number of name components */
-#define MAX_COMPONENTS 10
-
-/**
- print a nbt string
-*/
-_PUBLIC_ void ndr_print_nbt_string(struct ndr_print *ndr, const char *name, const char *s)
-{
- ndr_print_string(ndr, name, s);
-}
-
-/*
- pull one component of a nbt_string
-*/
-static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr,
- uint8_t **component,
- uint32_t *offset,
- uint32_t *max_offset)
-{
- uint8_t len;
- uint_t loops = 0;
- while (loops < 5) {
- if (*offset >= ndr->data_size) {
- return ndr_pull_error(ndr, NDR_ERR_STRING,
- "BAD NBT NAME component");
- }
- len = ndr->data[*offset];
- if (len == 0) {
- *offset += 1;
- *max_offset = MAX(*max_offset, *offset);
- *component = NULL;
- return NDR_ERR_SUCCESS;
- }
- if ((len & 0xC0) == 0xC0) {
- /* its a label pointer */
- if (1 + *offset >= ndr->data_size) {
- return ndr_pull_error(ndr, NDR_ERR_STRING,
- "BAD NBT NAME component");
- }
- *max_offset = MAX(*max_offset, *offset + 2);
- *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset];
- *max_offset = MAX(*max_offset, *offset);
- loops++;
- continue;
- }
- if ((len & 0xC0) != 0) {
- /* its a reserved length field */
- return ndr_pull_error(ndr, NDR_ERR_STRING,
- "BAD NBT NAME component");
- }
- if (*offset + len + 2 > ndr->data_size) {
- return ndr_pull_error(ndr, NDR_ERR_STRING,
- "BAD NBT NAME component");
- }
- *component = (uint8_t*)talloc_strndup(ndr, (const char *)&ndr->data[1 + *offset], len);
- NDR_ERR_HAVE_NO_MEMORY(*component);
- *offset += len + 1;
- *max_offset = MAX(*max_offset, *offset);
- return NDR_ERR_SUCCESS;
- }
-
- /* too many pointers */
- return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD NBT NAME component");
-}
-
-/**
- pull a nbt_string from the wire
-*/
-_PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
-{
- uint32_t offset = ndr->offset;
- uint32_t max_offset = offset;
- unsigned num_components;
- char *name;
-
- if (!(ndr_flags & NDR_SCALARS)) {
- return NDR_ERR_SUCCESS;
- }
-
- name = NULL;
-
- /* break up name into a list of components */
- for (num_components=0;num_components<MAX_COMPONENTS;num_components++) {
- uint8_t *component = NULL;
- NDR_CHECK(ndr_pull_component(ndr, &component, &offset, &max_offset));
- if (component == NULL) break;
- if (name) {
- name = talloc_asprintf_append_buffer(name, ".%s", component);
- NDR_ERR_HAVE_NO_MEMORY(name);
- } else {
- name = (char *)component;
- }
- }
- if (num_components == MAX_COMPONENTS) {
- return ndr_pull_error(ndr, NDR_ERR_STRING,
- "BAD NBT NAME too many components");
- }
- if (num_components == 0) {
- name = talloc_strdup(ndr, "");
- NDR_ERR_HAVE_NO_MEMORY(name);
- }
-
- (*s) = name;
- ndr->offset = max_offset;
-
- return NDR_ERR_SUCCESS;
-}
-
-/**
- push a nbt string to the wire
-*/
-_PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s)
-{
- if (!(ndr_flags & NDR_SCALARS)) {
- return NDR_ERR_SUCCESS;
- }
-
- while (s && *s) {
- enum ndr_err_code ndr_err;
- char *compname;
- size_t complen;
- uint32_t offset;
-
- /* see if we have pushed the remaing string allready,
- * if so we use a label pointer to this string
- */
- ndr_err = ndr_token_retrieve_cmp_fn(&ndr->nbt_string_list, s, &offset, (comparison_fn_t)strcmp, false);
- if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- uint8_t b[2];
-
- if (offset > 0x3FFF) {
- return ndr_push_error(ndr, NDR_ERR_STRING,
- "offset for nbt string label pointer %u[%08X] > 0x00003FFF",
- offset, offset);
- }
-
- b[0] = 0xC0 | (offset>>8);
- b[1] = (offset & 0xFF);
-
- return ndr_push_bytes(ndr, b, 2);
- }
-
- complen = strcspn(s, ".");
-
- /* we need to make sure the length fits into 6 bytes */
- if (complen >= 0x3F) {
- return ndr_push_error(ndr, NDR_ERR_STRING,
- "component length %u[%08X] > 0x00003F",
- (unsigned)complen, (unsigned)complen);
- }
-
- compname = talloc_asprintf(ndr, "%c%*.*s",
- (unsigned char)complen,
- (unsigned char)complen,
- (unsigned char)complen, s);
- NDR_ERR_HAVE_NO_MEMORY(compname);
-
- /* remember the current componemt + the rest of the string
- * so it can be reused later
- */
- NDR_CHECK(ndr_token_store(ndr, &ndr->nbt_string_list, s, ndr->offset));
-
- /* push just this component into the blob */
- NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, complen+1));
- talloc_free(compname);
-
- s += complen;
- if (*s == '.') s++;
- }
-
- /* if we reach the end of the string and have pushed the last component
- * without using a label pointer, we need to terminate the string
- */
- return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
-}
-
-
-/*
- decompress a 'compressed' name component
- */
-static bool decompress_name(char *name, enum nbt_name_type *type)
-{
- int i;
- for (i=0;name[2*i];i++) {
- uint8_t c1 = name[2*i];
- uint8_t c2 = name[1+(2*i)];
- if (c1 < 'A' || c1 > 'P' ||
- c2 < 'A' || c2 > 'P') {
- return false;
- }
- name[i] = ((c1-'A')<<4) | (c2-'A');
- }
- name[i] = 0;
- if (i == 16) {
- *type = (enum nbt_name_type)(name[15]);
- name[15] = 0;
- i--;
- } else {
- *type = NBT_NAME_CLIENT;
- }
-
- /* trim trailing spaces */
- for (;i>0 && name[i-1]==' ';i--) {
- name[i-1] = 0;
- }
-
- return true;
-}
-
-
-/*
- compress a name component
- */
-static uint8_t *compress_name(TALLOC_CTX *mem_ctx,
- const uint8_t *name, enum nbt_name_type type)
-{
- uint8_t *cname;
- int i;
- uint8_t pad_char;
-
- if (strlen((const char *)name) > 15) {
- return NULL;
- }
-
- cname = talloc_array(mem_ctx, uint8_t, 33);
- if (cname == NULL) return NULL;
-
- for (i=0;name[i];i++) {
- cname[2*i] = 'A' + (name[i]>>4);
- cname[1+2*i] = 'A' + (name[i]&0xF);
- }
- if (strcmp((const char *)name, "*") == 0) {
- pad_char = 0;
- } else {
- pad_char = ' ';
- }
- for (;i<15;i++) {
- cname[2*i] = 'A' + (pad_char>>4);
- cname[1+2*i] = 'A' + (pad_char&0xF);
- }
-
- pad_char = type;
- cname[2*i] = 'A' + (pad_char>>4);
- cname[1+2*i] = 'A' + (pad_char&0xF);
-
- cname[32] = 0;
- return cname;
-}
-
-
-/**
- pull a nbt name from the wire
-*/
-_PUBLIC_ enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r)
-{
- uint8_t *scope;
- char *cname;
- const char *s;
- bool ok;
-
- if (!(ndr_flags & NDR_SCALARS)) {
- return NDR_ERR_SUCCESS;
- }
-
- NDR_CHECK(ndr_pull_nbt_string(ndr, ndr_flags, &s));
-
- scope = (uint8_t *)strchr(s, '.');
- if (scope) {
- *scope = 0;
- r->scope = talloc_strdup(ndr->current_mem_ctx, (const char *)&scope[1]);
- NDR_ERR_HAVE_NO_MEMORY(r->scope);
- } else {
- r->scope = NULL;
- }
-
- cname = discard_const_p(char, s);
-
- /* the first component is limited to 16 bytes in the DOS charset,
- which is 32 in the 'compressed' form */
- if (strlen(cname) > 32) {
- return ndr_pull_error(ndr, NDR_ERR_STRING,
- "NBT NAME cname > 32");
- }
-
- /* decompress the first component */
- ok = decompress_name(cname, &r->type);
- if (!ok) {
- return ndr_pull_error(ndr, NDR_ERR_STRING,
- "NBT NAME failed to decompress");
- }
-
- r->name = talloc_strdup(ndr->current_mem_ctx, cname);
- NDR_ERR_HAVE_NO_MEMORY(r->name);
-
- talloc_free(cname);
-
- return NDR_ERR_SUCCESS;
-}
-
-/**
- push a nbt name to the wire
-*/
-_PUBLIC_ enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r)
-{
- uint8_t *cname, *fullname;
- enum ndr_err_code ndr_err;
-
- if (!(ndr_flags & NDR_SCALARS)) {
- return NDR_ERR_SUCCESS;
- }
-
- if (strlen(r->name) > 15) {
- return ndr_push_error(ndr, NDR_ERR_STRING,
- "nbt_name longer as 15 chars: %s",
- r->name);
- }
-
- cname = compress_name(ndr, (const uint8_t *)r->name, r->type);
- NDR_ERR_HAVE_NO_MEMORY(cname);
-
- if (r->scope) {
- fullname = (uint8_t *)talloc_asprintf(ndr, "%s.%s", cname, r->scope);
- NDR_ERR_HAVE_NO_MEMORY(fullname);
- talloc_free(cname);
- } else {
- fullname = cname;
- }
-
- ndr_err = ndr_push_nbt_string(ndr, ndr_flags, (const char *)fullname);
-
- return ndr_err;
-}
-
-
-/**
- copy a nbt name structure
-*/
-_PUBLIC_ NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname)
-{
- *newname = *name;
- newname->name = talloc_strdup(mem_ctx, newname->name);
- NT_STATUS_HAVE_NO_MEMORY(newname->name);
- newname->scope = talloc_strdup(mem_ctx, newname->scope);
- if (name->scope) {
- NT_STATUS_HAVE_NO_MEMORY(newname->scope);
- }
- return NT_STATUS_OK;
-}
-
-/**
- push a nbt name into a blob
-*/
-_PUBLIC_ NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct nbt_name *name)
-{
- enum ndr_err_code ndr_err;
-
- ndr_err = ndr_push_struct_blob(blob, mem_ctx, name, (ndr_push_flags_fn_t)ndr_push_nbt_name);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return ndr_map_error2ntstatus(ndr_err);
- }
-
- return NT_STATUS_OK;
-}
-
-/**
- pull a nbt name from a blob
-*/
-_PUBLIC_ NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name)
-{
- enum ndr_err_code ndr_err;
-
- ndr_err = ndr_pull_struct_blob(blob, mem_ctx, name,
- (ndr_pull_flags_fn_t)ndr_pull_nbt_name);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return ndr_map_error2ntstatus(ndr_err);
- }
-
- return NT_STATUS_OK;
-}
-
-
-/**
- choose a name to use when calling a server in a NBT session request.
- we use heuristics to see if the name we have been given is a IP
- address, or a too-long name. If it is then use *SMBSERVER, or a
- truncated name
-*/
-_PUBLIC_ void nbt_choose_called_name(TALLOC_CTX *mem_ctx,
- struct nbt_name *n, const char *name, int type)
-{
- n->scope = NULL;
- n->type = type;
-
- if ((name == NULL) || is_ipaddress(name)) {
- n->name = "*SMBSERVER";
- return;
- }
- if (strlen(name) > 15) {
- const char *p = strchr(name, '.');
- char *s;
- if (p - name > 15) {
- n->name = "*SMBSERVER";
- return;
- }
- s = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name));
- n->name = talloc_strdup_upper(mem_ctx, s);
- return;
- }
-
- n->name = talloc_strdup_upper(mem_ctx, name);
-}
-
-
-/*
- escape a string into a form containing only a small set of characters,
- the rest is hex encoded. This is similar to URL encoding
-*/
-static const char *nbt_hex_encode(TALLOC_CTX *mem_ctx, const char *s)
-{
- int i, len;
- char *ret;
- const char *valid_chars = "_-.$@ ";
-#define NBT_CHAR_ALLOW(c) (isalnum((unsigned char)c) || strchr(valid_chars, c))
-
- for (len=i=0;s[i];i++,len++) {
- if (!NBT_CHAR_ALLOW(s[i])) {
- len += 2;
- }
- }
-
- ret = talloc_array(mem_ctx, char, len+1);
- if (ret == NULL) return NULL;
-
- for (len=i=0;s[i];i++) {
- if (NBT_CHAR_ALLOW(s[i])) {
- ret[len++] = s[i];
- } else {
- snprintf(&ret[len], 4, "%%%02x", (unsigned char)s[i]);
- len += 3;
- }
- }
- ret[len] = 0;
-
- return ret;
-}
-
-
-/**
- form a string for a NBT name
-*/
-_PUBLIC_ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name)
-{
- TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
- char *ret;
- if (name->scope) {
- ret = talloc_asprintf(mem_ctx, "%s<%02x>-%s",
- nbt_hex_encode(tmp_ctx, name->name),
- name->type,
- nbt_hex_encode(tmp_ctx, name->scope));
- } else {
- ret = talloc_asprintf(mem_ctx, "%s<%02x>",
- nbt_hex_encode(tmp_ctx, name->name),
- name->type);
- }
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/**
- pull a nbt name, WINS Replication uses another on wire format for nbt name
-*/
-_PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, const struct nbt_name **_r)
-{
- struct nbt_name *r;
- uint8_t *namebuf;
- uint32_t namebuf_len;
-
- if (!(ndr_flags & NDR_SCALARS)) {
- return NDR_ERR_SUCCESS;
- }
-
- NDR_CHECK(ndr_pull_align(ndr, 4));
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &namebuf_len));
- if (namebuf_len < 1 || namebuf_len > 255) {
- return ndr_pull_error(ndr, NDR_ERR_ALLOC, "value out of range");
- }
- NDR_PULL_ALLOC_N(ndr, namebuf, namebuf_len);
- NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len));
-
- NDR_PULL_ALLOC(ndr, r);
-
- /* oh wow, what a nasty bug in windows ... */
- if (namebuf[0] == 0x1b && namebuf_len >= 16) {
- namebuf[0] = namebuf[15];
- namebuf[15] = 0x1b;
- }
-
- if (namebuf_len < 17) {
- r->type = 0x00;
-
- r->name = talloc_strndup(r, (char *)namebuf, namebuf_len);
- if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
-
- r->scope= NULL;
-
- talloc_free(namebuf);
- *_r = r;
- return NDR_ERR_SUCCESS;
- }
-
- r->type = namebuf[15];
-
- namebuf[15] = '\0';
- trim_string((char *)namebuf, NULL, " ");
- r->name = talloc_strdup(r, (char *)namebuf);
- if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
-
- if (namebuf_len > 18) {
- r->scope = talloc_strndup(r, (char *)(namebuf+17), namebuf_len-17);
- if (!r->scope) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
- } else {
- r->scope = NULL;
- }
-
- talloc_free(namebuf);
- *_r = r;
- return NDR_ERR_SUCCESS;
-}
-
-/**
- push a nbt name, WINS Replication uses another on wire format for nbt name
-*/
-_PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r)
-{
- uint8_t *namebuf;
- uint32_t namebuf_len;
- uint32_t _name_len;
- uint32_t scope_len = 0;
-
- if (r == NULL) {
- return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER,
- "wrepl_nbt_name NULL pointer");
- }
-
- if (!(ndr_flags & NDR_SCALARS)) {
- return NDR_ERR_SUCCESS;
- }
-
- _name_len = strlen(r->name);
- if (_name_len > 15) {
- return ndr_push_error(ndr, NDR_ERR_STRING,
- "wrepl_nbt_name longer as 15 chars: %s",
- r->name);
- }
-
- if (r->scope) {
- scope_len = strlen(r->scope);
- }
- if (scope_len > 238) {
- return ndr_push_error(ndr, NDR_ERR_STRING,
- "wrepl_nbt_name scope longer as 238 chars: %s",
- r->scope);
- }
-
- namebuf = (uint8_t *)talloc_asprintf(ndr, "%-15s%c%s",
- r->name, 'X',
- (r->scope?r->scope:""));
- if (!namebuf) return ndr_push_error(ndr, NDR_ERR_ALLOC, "out of memory");
-
- namebuf_len = strlen((char *)namebuf) + 1;
-
- /*
- * we need to set the type here, and use a place-holder in the talloc_asprintf()
- * as the type can be 0x00, and then the namebuf_len = strlen(namebuf); would give wrong results
- */
- namebuf[15] = r->type;
-
- /* oh wow, what a nasty bug in windows ... */
- if (r->type == 0x1b) {
- namebuf[15] = namebuf[0];
- namebuf[0] = 0x1b;
- }
-
- NDR_CHECK(ndr_push_align(ndr, 4));
- NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, namebuf_len));
- NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len));
-
- talloc_free(namebuf);
- return NDR_ERR_SUCCESS;
-}
-
-_PUBLIC_ void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r)
-{
- char *s = nbt_name_string(ndr, r);
- ndr_print_string(ndr, name, s);
- talloc_free(s);
-}
diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c
index 6ba2c3aa41..e762ecbe49 100644
--- a/source3/libnet/libnet_dssync_keytab.c
+++ b/source3/libnet/libnet_dssync_keytab.c
@@ -86,7 +86,7 @@ static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
old_utdv = talloc(mem_ctx, struct replUpToDateVectorBlob);
ndr_err = ndr_pull_struct_blob(&entry->password, old_utdv,
- old_utdv,
+ NULL, old_utdv,
(ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
@@ -124,7 +124,7 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
NDR_PRINT_DEBUG(replUpToDateVectorBlob, new_utdv);
}
- ndr_err = ndr_push_struct_blob(&blob, mem_ctx, new_utdv,
+ ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, new_utdv,
(ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
@@ -236,7 +236,7 @@ static NTSTATUS parse_supplemental_credentials(TALLOC_CTX *mem_ctx,
status = NT_STATUS_NO_MEMORY;
goto done;
}
- ndr_err = ndr_pull_struct_blob(&scpk_blob, mem_ctx, pkb,
+ ndr_err = ndr_pull_struct_blob(&scpk_blob, mem_ctx, NULL, pkb,
(ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c
index daf27ffb51..64dcf6de51 100644
--- a/source3/libnet/libnet_samsync.c
+++ b/source3/libnet/libnet_samsync.c
@@ -65,7 +65,7 @@ static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
user->user_private_info.SensitiveData = data.data;
user->user_private_info.DataLength = data.length;
- ndr_err = ndr_pull_struct_blob(&data, mem_ctx, &keys,
+ ndr_err = ndr_pull_struct_blob(&data, mem_ctx, NULL, &keys,
(ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
dump_data(10, data.data, data.length);
@@ -397,7 +397,7 @@ NTSTATUS pull_netr_AcctLockStr(TALLOC_CTX *mem_ctx,
blob = data_blob_const(r->array, r->length);
- ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, str,
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, str,
(ndr_pull_flags_fn_t)ndr_pull_netr_AcctLockStr);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
diff --git a/source3/librpc/gen_ndr/libnetapi.h b/source3/librpc/gen_ndr/libnetapi.h
index 98da9e12ea..ae7acbf572 100644
--- a/source3/librpc/gen_ndr/libnetapi.h
+++ b/source3/librpc/gen_ndr/libnetapi.h
@@ -413,7 +413,9 @@ struct USER_INFO_X {
uint32_t usriX_code_page;
const char * usriX_profile;
const char * usriX_home_dir_drive;
+ uint32_t usriX_user_id;
uint32_t usriX_primary_group_id;
+ uint32_t usriX_password_expired;
};
struct GROUP_USERS_INFO_0 {
diff --git a/source3/librpc/gen_ndr/nbt.h b/source3/librpc/gen_ndr/nbt.h
index 62ad524a91..0943ee1a4d 100644
--- a/source3/librpc/gen_ndr/nbt.h
+++ b/source3/librpc/gen_ndr/nbt.h
@@ -221,7 +221,7 @@ union nbt_rdata {
struct nbt_rdata_netbios netbios;/* [case(NBT_QTYPE_NETBIOS)] */
struct nbt_rdata_status status;/* [case(NBT_QTYPE_STATUS)] */
struct nbt_rdata_data data;/* [default] */
-}/* [nodiscriminant] */;
+}/* [nodiscriminant,public] */;
struct nbt_res_rec {
struct nbt_name name;
diff --git a/source3/librpc/gen_ndr/ndr_libnetapi.c b/source3/librpc/gen_ndr/ndr_libnetapi.c
index a5266827b6..d7bf63e62f 100644
--- a/source3/librpc/gen_ndr/ndr_libnetapi.c
+++ b/source3/librpc/gen_ndr/ndr_libnetapi.c
@@ -1895,7 +1895,9 @@ _PUBLIC_ enum ndr_err_code ndr_push_USER_INFO_X(struct ndr_push *ndr, int ndr_fl
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_code_page));
NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->usriX_profile));
NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->usriX_home_dir_drive));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_user_id));
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_primary_group_id));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_password_expired));
}
if (ndr_flags & NDR_BUFFERS) {
if (r->usriX_logon_hours) {
@@ -1942,7 +1944,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_USER_INFO_X(struct ndr_pull *ndr, int ndr_fl
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_code_page));
NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->usriX_profile));
NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->usriX_home_dir_drive));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_user_id));
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_primary_group_id));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_password_expired));
}
if (ndr_flags & NDR_BUFFERS) {
if (r->usriX_logon_hours) {
@@ -1990,7 +1994,9 @@ _PUBLIC_ void ndr_print_USER_INFO_X(struct ndr_print *ndr, const char *name, con
ndr_print_uint32(ndr, "usriX_code_page", r->usriX_code_page);
ndr_print_string(ndr, "usriX_profile", r->usriX_profile);
ndr_print_string(ndr, "usriX_home_dir_drive", r->usriX_home_dir_drive);
+ ndr_print_uint32(ndr, "usriX_user_id", r->usriX_user_id);
ndr_print_uint32(ndr, "usriX_primary_group_id", r->usriX_primary_group_id);
+ ndr_print_uint32(ndr, "usriX_password_expired", r->usriX_password_expired);
ndr->depth--;
}
diff --git a/source3/librpc/gen_ndr/ndr_nbt.c b/source3/librpc/gen_ndr/ndr_nbt.c
index 75667183a8..01cccd6742 100644
--- a/source3/librpc/gen_ndr/ndr_nbt.c
+++ b/source3/librpc/gen_ndr/ndr_nbt.c
@@ -77,13 +77,13 @@ _PUBLIC_ void ndr_print_nbt_name(struct ndr_print *ndr, const char *name, const
ndr->depth--;
}
-static enum ndr_err_code ndr_push_nbt_qclass(struct ndr_push *ndr, int ndr_flags, enum nbt_qclass r)
+_PUBLIC_ enum ndr_err_code ndr_push_nbt_qclass(struct ndr_push *ndr, int ndr_flags, enum nbt_qclass r)
{
NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r));
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_nbt_qclass(struct ndr_pull *ndr, int ndr_flags, enum nbt_qclass *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_nbt_qclass(struct ndr_pull *ndr, int ndr_flags, enum nbt_qclass *r)
{
uint16_t v;
NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &v));
@@ -101,13 +101,13 @@ _PUBLIC_ void ndr_print_nbt_qclass(struct ndr_print *ndr, const char *name, enum
ndr_print_enum(ndr, name, "ENUM", val, r);
}
-static enum ndr_err_code ndr_push_nbt_qtype(struct ndr_push *ndr, int ndr_flags, enum nbt_qtype r)
+_PUBLIC_ enum ndr_err_code ndr_push_nbt_qtype(struct ndr_push *ndr, int ndr_flags, enum nbt_qtype r)
{
NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r));
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_nbt_qtype(struct ndr_pull *ndr, int ndr_flags, enum nbt_qtype *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_nbt_qtype(struct ndr_pull *ndr, int ndr_flags, enum nbt_qtype *r)
{
uint16_t v;
NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &v));
@@ -496,7 +496,7 @@ _PUBLIC_ void ndr_print_nbt_rdata_data(struct ndr_print *ndr, const char *name,
ndr->depth--;
}
-static enum ndr_err_code ndr_push_nbt_rdata(struct ndr_push *ndr, int ndr_flags, const union nbt_rdata *r)
+_PUBLIC_ enum ndr_err_code ndr_push_nbt_rdata(struct ndr_push *ndr, int ndr_flags, const union nbt_rdata *r)
{
if (ndr_flags & NDR_SCALARS) {
int level = ndr_push_get_switch_value(ndr, r);
@@ -532,7 +532,7 @@ static enum ndr_err_code ndr_push_nbt_rdata(struct ndr_push *ndr, int ndr_flags,
return NDR_ERR_SUCCESS;
}
-static enum ndr_err_code ndr_pull_nbt_rdata(struct ndr_pull *ndr, int ndr_flags, union nbt_rdata *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_nbt_rdata(struct ndr_pull *ndr, int ndr_flags, union nbt_rdata *r)
{
int level;
level = ndr_pull_get_switch_value(ndr, r);
diff --git a/source3/librpc/gen_ndr/ndr_nbt.h b/source3/librpc/gen_ndr/ndr_nbt.h
index 6e9702d5d5..f70d1ba8df 100644
--- a/source3/librpc/gen_ndr/ndr_nbt.h
+++ b/source3/librpc/gen_ndr/ndr_nbt.h
@@ -6,14 +6,18 @@
#ifndef _HEADER_NDR_nbt
#define _HEADER_NDR_nbt
-#include "libcli/nbt/libnbt.h"
+#include "../libcli/nbt/libnbt.h"
#define NDR_NBT_CALL_COUNT (0)
void ndr_print_nbt_operation(struct ndr_print *ndr, const char *name, uint16_t r);
void ndr_print_nbt_name_type(struct ndr_print *ndr, const char *name, enum nbt_name_type r);
enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r);
enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r);
void ndr_print_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r);
+enum ndr_err_code ndr_push_nbt_qclass(struct ndr_push *ndr, int ndr_flags, enum nbt_qclass r);
+enum ndr_err_code ndr_pull_nbt_qclass(struct ndr_pull *ndr, int ndr_flags, enum nbt_qclass *r);
void ndr_print_nbt_qclass(struct ndr_print *ndr, const char *name, enum nbt_qclass r);
+enum ndr_err_code ndr_push_nbt_qtype(struct ndr_push *ndr, int ndr_flags, enum nbt_qtype r);
+enum ndr_err_code ndr_pull_nbt_qtype(struct ndr_pull *ndr, int ndr_flags, enum nbt_qtype *r);
void ndr_print_nbt_qtype(struct ndr_print *ndr, const char *name, enum nbt_qtype r);
void ndr_print_nbt_name_question(struct ndr_print *ndr, const char *name, const struct nbt_name_question *r);
void ndr_print_nb_flags(struct ndr_print *ndr, const char *name, uint16_t r);
@@ -23,6 +27,8 @@ void ndr_print_nbt_statistics(struct ndr_print *ndr, const char *name, const str
void ndr_print_nbt_status_name(struct ndr_print *ndr, const char *name, const struct nbt_status_name *r);
void ndr_print_nbt_rdata_status(struct ndr_print *ndr, const char *name, const struct nbt_rdata_status *r);
void ndr_print_nbt_rdata_data(struct ndr_print *ndr, const char *name, const struct nbt_rdata_data *r);
+enum ndr_err_code ndr_push_nbt_rdata(struct ndr_push *ndr, int ndr_flags, const union nbt_rdata *r);
+enum ndr_err_code ndr_pull_nbt_rdata(struct ndr_pull *ndr, int ndr_flags, union nbt_rdata *r);
void ndr_print_nbt_rdata(struct ndr_print *ndr, const char *name, const union nbt_rdata *r);
void ndr_print_nbt_res_rec(struct ndr_print *ndr, const char *name, const struct nbt_res_rec *r);
enum ndr_err_code ndr_push_nbt_name_packet(struct ndr_push *ndr, int ndr_flags, const struct nbt_name_packet *r);
diff --git a/source3/librpc/idl/libnetapi.idl b/source3/librpc/idl/libnetapi.idl
index 039dcf4152..f2f4a16c12 100644
--- a/source3/librpc/idl/libnetapi.idl
+++ b/source3/librpc/idl/libnetapi.idl
@@ -517,7 +517,9 @@ interface libnetapi
uint32 usriX_code_page;
string usriX_profile;
string usriX_home_dir_drive;
+ uint32 usriX_user_id;
uint32 usriX_primary_group_id;
+ uint32 usriX_password_expired;
} USER_INFO_X;
[nopush,nopull] NET_API_STATUS NetUserAdd(
diff --git a/source3/librpc/idl/nbt.idl b/source3/librpc/idl/nbt.idl
index 654f53c52f..da1eb2ef3f 100644
--- a/source3/librpc/idl/nbt.idl
+++ b/source3/librpc/idl/nbt.idl
@@ -10,7 +10,7 @@
import "misc.idl", "security.idl", "svcctl.idl", "samr.idl";
[
-helper("libcli/nbt/libnbt.h")
+helper("../libcli/nbt/libnbt.h")
]
interface nbt
{
@@ -73,11 +73,11 @@ interface nbt
nbt_name_type type;
} nbt_name;
- typedef [enum16bit] enum {
+ typedef [public,enum16bit] enum {
NBT_QCLASS_IP = 0x01
} nbt_qclass;
- typedef [enum16bit] enum {
+ typedef [public,enum16bit] enum {
NBT_QTYPE_ADDRESS = 0x0001,
NBT_QTYPE_NAMESERVICE = 0x0002,
NBT_QTYPE_NULL = 0x000A,
@@ -160,7 +160,7 @@ interface nbt
uint8 data[length];
} nbt_rdata_data;
- typedef [nodiscriminant] union {
+ typedef [nodiscriminant,public] union {
[case(NBT_QTYPE_NETBIOS)] nbt_rdata_netbios netbios;
[case(NBT_QTYPE_STATUS)] nbt_rdata_status status;
[default] nbt_rdata_data data;
diff --git a/source3/librpc/ndr/ndr.c b/source3/librpc/ndr/ndr.c
index d94d12e146..624024c94d 100644
--- a/source3/librpc/ndr/ndr.c
+++ b/source3/librpc/ndr/ndr.c
@@ -803,8 +803,11 @@ _PUBLIC_ uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *
/*
pull a struct from a blob using NDR
*/
-_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
- ndr_pull_flags_fn_t fn)
+_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob,
+ TALLOC_CTX *mem_ctx,
+ struct smb_iconv_convenience *iconv_convenience,
+ void *p,
+ ndr_pull_flags_fn_t fn)
{
struct ndr_pull *ndr;
ndr = ndr_pull_init_blob(blob, mem_ctx);
@@ -868,8 +871,11 @@ _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC
/*
push a struct to a blob using NDR
*/
-_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p,
- ndr_push_flags_fn_t fn)
+_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob,
+ TALLOC_CTX *mem_ctx,
+ struct smb_iconv_convenience *iconv_convenience,
+ const void *p,
+ ndr_push_flags_fn_t fn)
{
struct ndr_push *ndr;
ndr = ndr_push_init_ctx(mem_ctx);
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 8b35a69def..8ee3507a04 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -181,7 +181,7 @@ bool send_getdc_request(TALLOC_CTX *mem_ctx,
NDR_PRINT_DEBUG(nbt_ntlogon_packet, &packet);
}
- ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &packet,
+ ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &packet,
(ndr_push_flags_fn_t)ndr_push_nbt_ntlogon_packet);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return false;
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 9d65fb4e94..8a5aedfde5 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -464,13 +464,11 @@ struct cli_state *cli_initialise(void)
return NULL;
}
- cli = talloc(NULL, struct cli_state);
+ cli = TALLOC_ZERO_P(NULL, struct cli_state);
if (!cli) {
return NULL;
}
- ZERO_STRUCTP(cli);
-
cli->port = 0;
cli->fd = -1;
cli->cnum = -1;
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 2a445cbd5a..e822635546 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -331,7 +331,7 @@ static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
return status;
}
- ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &logon29,
+ ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &logon29,
(ndr_push_flags_fn_t)ndr_push_nbt_cldap_netlogon_29);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return ndr_map_error2ntstatus(ndr_err);
@@ -508,7 +508,7 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
return NT_STATUS_NO_MEMORY;
}
- ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r,
(ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon_29);
data_blob_free(&blob);
diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c
index 4abe5bb6de..af4986fa9d 100644
--- a/source3/libsmb/samlogon_cache.c
+++ b/source3/libsmb/samlogon_cache.c
@@ -141,7 +141,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
}
- ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r,
+ ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &r,
(ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
@@ -197,7 +197,7 @@ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *
blob = data_blob_const(data.dptr, data.dsize);
- ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r,
(ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
if (DEBUGLEVEL >= 10) {
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index 08a49930b4..2f336f14e6 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -22,104 +22,6 @@
/*********************************************************
Change the domain password on the PDC.
-
- Just changes the password betwen the two values specified.
-
- Caller must have the cli connected to the netlogon pipe
- already.
-**********************************************************/
-
-static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- const unsigned char orig_trust_passwd_hash[16],
- const char *new_trust_pwd_cleartext,
- const unsigned char new_trust_passwd_hash[16],
- uint32 sec_channel_type)
-{
- NTSTATUS result;
- uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
-
- result = rpccli_netlogon_setup_creds(cli,
- cli->desthost, /* server name */
- lp_workgroup(), /* domain */
- global_myname(), /* client name */
- global_myname(), /* machine account name */
- orig_trust_passwd_hash,
- sec_channel_type,
- &neg_flags);
-
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
- nt_errstr(result)));
- return result;
- }
-
- if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
-
- struct netr_Authenticator clnt_creds, srv_cred;
- struct netr_CryptPassword new_password;
- struct samr_CryptPassword password_buf;
-
- netlogon_creds_client_step(cli->dc, &clnt_creds);
-
- encode_pw_buffer(password_buf.data, new_trust_pwd_cleartext, STR_UNICODE);
-
- SamOEMhash(password_buf.data, cli->dc->sess_key, 516);
- memcpy(new_password.data, password_buf.data, 512);
- new_password.length = IVAL(password_buf.data, 512);
-
- result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
- cli->dc->remote_machine,
- cli->dc->mach_acct,
- sec_channel_type,
- global_myname(),
- &clnt_creds,
- &srv_cred,
- &new_password);
-
- /* Always check returned credentials. */
- if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
- DEBUG(0,("rpccli_netr_ServerPasswordSet2: "
- "credentials chain check failed\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- } else {
-
- struct netr_Authenticator clnt_creds, srv_cred;
- struct samr_Password new_password;
-
- netlogon_creds_client_step(cli->dc, &clnt_creds);
-
- cred_hash3(new_password.hash,
- new_trust_passwd_hash,
- cli->dc->sess_key, 1);
-
- result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
- cli->dc->remote_machine,
- cli->dc->mach_acct,
- sec_channel_type,
- global_myname(),
- &clnt_creds,
- &srv_cred,
- &new_password);
-
- /* Always check returned credentials. */
- if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
- DEBUG(0,("rpccli_netr_ServerPasswordSet: "
- "credentials chain check failed\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
- }
-
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
- nt_errstr(result)));
- }
- return result;
-}
-
-/*********************************************************
- Change the domain password on the PDC.
Store the password ourselves, but use the supplied password
Caller must have already setup the connection to the NETLOGON pipe
**********************************************************/
@@ -144,11 +46,11 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m
E_md4hash(new_trust_passwd, new_trust_passwd_hash);
- nt_status = just_change_the_password(cli, mem_ctx,
- orig_trust_passwd_hash,
- new_trust_passwd,
- new_trust_passwd_hash,
- sec_channel_type);
+ nt_status = rpccli_netlogon_set_trust_password(cli, mem_ctx,
+ orig_trust_passwd_hash,
+ new_trust_passwd,
+ new_trust_passwd_hash,
+ sec_channel_type);
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c
index fd59310755..a2f3477b76 100644
--- a/source3/modules/vfs_acl_xattr.c
+++ b/source3/modules/vfs_acl_xattr.c
@@ -38,7 +38,7 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
size_t sd_size;
struct timespec ts;
- ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl,
+ ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
(ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -245,7 +245,7 @@ static NTSTATUS create_acl_blob(SEC_DESC *psd, DATA_BLOB *pblob)
unix_timespec_to_nt_time(&xacl.info.sd_ts->last_changed, curr);
ndr_err = ndr_push_struct_blob(
- pblob, ctx, &xacl,
+ pblob, ctx, NULL, &xacl,
(ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c
index 7b5e510747..c707a1828f 100644
--- a/source3/modules/vfs_xattr_tdb.c
+++ b/source3/modules/vfs_xattr_tdb.c
@@ -48,7 +48,7 @@ static NTSTATUS xattr_tdb_pull_attrs(TALLOC_CTX *mem_ctx,
blob = data_blob_const(data->dptr, data->dsize);
ndr_err = ndr_pull_struct_blob(
- &blob, result, result,
+ &blob, result, NULL, result,
(ndr_pull_flags_fn_t)ndr_pull_tdb_xattrs);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -74,7 +74,7 @@ static NTSTATUS xattr_tdb_push_attrs(TALLOC_CTX *mem_ctx,
enum ndr_err_code ndr_err;
ndr_err = ndr_push_struct_blob(
- &blob, mem_ctx, attribs,
+ &blob, mem_ctx, NULL, attribs,
(ndr_push_flags_fn_t)ndr_push_tdb_xattrs);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index df87ed13d1..23618efd9f 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -538,3 +538,94 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
return result;
}
+
+/*********************************************************
+ Change the domain password on the PDC.
+
+ Just changes the password betwen the two values specified.
+
+ Caller must have the cli connected to the netlogon pipe
+ already.
+**********************************************************/
+
+NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ const unsigned char orig_trust_passwd_hash[16],
+ const char *new_trust_pwd_cleartext,
+ const unsigned char new_trust_passwd_hash[16],
+ uint32_t sec_channel_type)
+{
+ NTSTATUS result;
+ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+ struct netr_Authenticator clnt_creds, srv_cred;
+
+ result = rpccli_netlogon_setup_creds(cli,
+ cli->desthost, /* server name */
+ lp_workgroup(), /* domain */
+ global_myname(), /* client name */
+ global_myname(), /* machine account name */
+ orig_trust_passwd_hash,
+ sec_channel_type,
+ &neg_flags);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
+ nt_errstr(result)));
+ return result;
+ }
+
+ netlogon_creds_client_step(cli->dc, &clnt_creds);
+
+ if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
+
+ struct netr_CryptPassword new_password;
+
+ init_netr_CryptPassword(new_trust_pwd_cleartext,
+ cli->dc->sess_key,
+ &new_password);
+
+ result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
+ cli->dc->remote_machine,
+ cli->dc->mach_acct,
+ sec_channel_type,
+ global_myname(),
+ &clnt_creds,
+ &srv_cred,
+ &new_password);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
+ nt_errstr(result)));
+ return result;
+ }
+ } else {
+
+ struct samr_Password new_password;
+
+ cred_hash3(new_password.hash,
+ new_trust_passwd_hash,
+ cli->dc->sess_key, 1);
+
+ result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
+ cli->dc->remote_machine,
+ cli->dc->mach_acct,
+ sec_channel_type,
+ global_myname(),
+ &clnt_creds,
+ &srv_cred,
+ &new_password);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
+ nt_errstr(result)));
+ return result;
+ }
+ }
+
+ /* Always check returned credentials. */
+ if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
+ DEBUG(0,("credentials chain check failed\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return result;
+}
+
diff --git a/source3/rpc_client/init_netlogon.c b/source3/rpc_client/init_netlogon.c
index 61841953fc..e4c39e739e 100644
--- a/source3/rpc_client/init_netlogon.c
+++ b/source3/rpc_client/init_netlogon.c
@@ -391,3 +391,20 @@ void init_netr_PasswordInfo(struct netr_PasswordInfo *r,
r->lmpassword = lmpassword;
r->ntpassword = ntpassword;
}
+
+/*************************************************************************
+ inits a netr_CryptPassword structure
+ *************************************************************************/
+
+void init_netr_CryptPassword(const char *pwd,
+ unsigned char session_key[16],
+ struct netr_CryptPassword *pwd_buf)
+{
+ struct samr_CryptPassword password_buf;
+
+ encode_pw_buffer(password_buf.data, pwd, STR_UNICODE);
+
+ SamOEMhash(password_buf.data, session_key, 516);
+ memcpy(pwd_buf->data, password_buf.data, 512);
+ pwd_buf->length = IVAL(password_buf.data, 512);
+}
diff --git a/source3/samba4.m4 b/source3/samba4.m4
index c02d3d4b3b..728fd2d45d 100644
--- a/source3/samba4.m4
+++ b/source3/samba4.m4
@@ -95,7 +95,6 @@ m4_include(ntvfs/unixuid/config.m4)
m4_include(auth/config.m4)
m4_include(kdc/config.m4)
m4_include(ntvfs/sysdep/config.m4)
-m4_include(lib/appweb/config.m4)
m4_include(nsswitch/config.m4)
dnl Samba 4 files
diff --git a/source3/samba4.mk b/source3/samba4.mk
index 294eef8b8f..2646b12a0d 100644
--- a/source3/samba4.mk
+++ b/source3/samba4.mk
@@ -7,7 +7,7 @@ PARTLINK = $(PROG_LD) -r
MDLD = $(SHLD)
MDLD_FLAGS = $(LDSHFLAGS)
-samba4srcdir = $(call abspath,$(srcdir)/../source4)
+samba4srcdir = $(srcdir)/../source4
# Flags used for the samba 4 files
# $(srcdir)/include is required for config.h
@@ -83,7 +83,6 @@ libcmdlinesrcdir := $(samba4srcdir)/lib/cmdline
poptsrcdir := $(samba4srcdir)/../lib/popt
socketwrappersrcdir := $(samba4srcdir)/../lib/socket_wrapper
nsswrappersrcdir := $(samba4srcdir)/../lib/nss_wrapper
-appwebsrcdir := $(samba4srcdir)/lib/appweb
libstreamsrcdir := $(samba4srcdir)/lib/stream
libutilsrcdir := $(samba4srcdir)/lib/util
libtdrsrcdir := $(samba4srcdir)/lib/tdr
@@ -108,7 +107,6 @@ ntvfssrcdir := $(samba4srcdir)/ntvfs
ntptrsrcdir := $(samba4srcdir)/ntptr
clientsrcdir := $(samba4srcdir)/client
libclisrcdir := $(samba4srcdir)/libcli
-ejsscriptsrcdir := $(samba4srcdir)/scripting/ejs
pyscriptsrcdir := $(samba4srcdir)/scripting/python
kdcsrcdir := $(samba4srcdir)/kdc
smbreadlinesrcdir := $(samba4srcdir)/lib/smbreadline
@@ -116,6 +114,7 @@ ntp_signdsrcdir := $(samba4srcdir)/ntp_signd
tdbsrcdir := $(samba4srcdir)/../lib/tdb
ldbsrcdir := $(samba4srcdir)/lib/ldb
tallocsrcdir := $(samba4srcdir)/../lib/talloc
+comsrcdir := $(samba4srcdir)/lib/com
override ASN1C = bin/asn1_compile4
override ET_COMPILER = bin/compile_et4
include samba4-data.mk
diff --git a/source3/script/build_idl.sh b/source3/script/build_idl.sh
index 8ff5dcd949..2027fd3937 100755
--- a/source3/script/build_idl.sh
+++ b/source3/script/build_idl.sh
@@ -19,7 +19,7 @@ for f in ${IDL_FILES}; do
basename=`basename $f .idl`
ndr="librpc/gen_ndr/ndr_$basename.c"
- if [ -f $ndr ] && false; then
+ if [ -f $ndr ]; then
if [ "x`find librpc/idl/$f -newer $ndr -print`" = "xlibrpc/idl/$f" ]; then
list="$list librpc/idl/$f"
fi
diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c
index 84b8e1098e..06da717799 100644
--- a/source3/smbd/notify_internal.c
+++ b/source3/smbd/notify_internal.c
@@ -166,7 +166,7 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
status = NT_STATUS_OK;
if (blob.length > 0) {
enum ndr_err_code ndr_err;
- ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->array,
+ ndr_err = ndr_pull_struct_blob(&blob, notify->array, NULL, notify->array,
(ndr_pull_flags_fn_t)ndr_pull_notify_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
@@ -220,7 +220,7 @@ static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec
tmp_ctx = talloc_new(notify);
NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
- ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, notify->array,
+ ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL, notify->array,
(ndr_push_flags_fn_t)ndr_push_notify_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
@@ -258,7 +258,7 @@ static void notify_handler(struct messaging_context *msg_ctx, void *private_data
return;
}
- ndr_err = ndr_pull_struct_blob(data, tmp_ctx, &ev,
+ ndr_err = ndr_pull_struct_blob(data, tmp_ctx, NULL, &ev,
(ndr_pull_flags_fn_t)ndr_pull_notify_event);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
@@ -561,7 +561,7 @@ static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry *
tmp_ctx = talloc_new(notify);
- ndr_err = ndr_push_struct_blob(&data, tmp_ctx, &ev,
+ ndr_err = ndr_push_struct_blob(&data, tmp_ctx, NULL, &ev,
(ndr_push_flags_fn_t)ndr_push_notify_event);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
diff --git a/source3/utils/net_rpc_registry.c b/source3/utils/net_rpc_registry.c
index 124af00b57..005e3ca556 100644
--- a/source3/utils/net_rpc_registry.c
+++ b/source3/utils/net_rpc_registry.c
@@ -1186,7 +1186,7 @@ static NTSTATUS rpc_registry_getsd_internal(struct net_context *c,
blob.data = sd->data;
blob.length = sd->size;
- ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &sec_desc,
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &sec_desc,
(ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
status = ndr_map_error2ntstatus(ndr_err);
diff --git a/source3/winbindd/idmap_adex/cell_util.c b/source3/winbindd/idmap_adex/cell_util.c
new file mode 100644
index 0000000000..f5c08a0454
--- /dev/null
+++ b/source3/winbindd/idmap_adex/cell_util.c
@@ -0,0 +1,292 @@
+/*
+ * idmap_adex: Support for AD Forests
+ *
+ * Copyright (C) Gerald (Jerry) Carter 2006-2008
+ *
+ * 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 "idmap_adex.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/**********************************************************************
+**********************************************************************/
+
+ char *find_attr_string(char **list, size_t num_lines, const char *substr)
+{
+ int i;
+ int cmplen = strlen(substr);
+
+ for (i = 0; i < num_lines; i++) {
+ /* make sure to avoid substring matches like uid
+ and uidNumber */
+ if ((StrnCaseCmp(list[i], substr, cmplen) == 0) &&
+ (list[i][cmplen] == '=')) {
+ /* Don't return an empty string */
+ if (list[i][cmplen + 1] != '\0')
+ return &(list[i][cmplen + 1]);
+
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+ bool is_object_class(char **list, size_t num_lines, const char *substr)
+{
+ int i;
+
+ for (i = 0; i < num_lines; i++) {
+ if (strequal(list[i], substr)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**********************************************************************
+ Find out about the cell (e.g. use2307Attrs, etc...)
+**********************************************************************/
+
+ NTSTATUS cell_lookup_settings(struct likewise_cell * cell)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ /* Parameter check */
+
+ if (!cell) {
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Only supporting Forest-wide, schema based searches */
+
+ cell_set_flags(cell, LWCELL_FLAG_USE_RFC2307_ATTRS);
+ cell_set_flags(cell, LWCELL_FLAG_SEARCH_FOREST);
+
+ cell->provider = &ccp_unified;
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1,("LWI: Failed to obtain cell settings (%s)\n",
+ nt_errstr(nt_status)));
+ }
+
+ return nt_status;
+}
+
+
+static NTSTATUS cell_lookup_forest(struct likewise_cell *c)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct gc_info *gc = NULL;
+
+ if (!c) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((gc = TALLOC_ZERO_P(NULL, struct gc_info)) == NULL) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Query the rootDSE for the forest root naming conect first.
+ Check that the a GC server for the forest has not already
+ been added */
+
+ nt_status = gc_find_forest_root(gc, cell_dns_domain(c));
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ c->forest_name = talloc_strdup(c, gc->forest_name);
+ BAIL_ON_PTR_ERROR(c->forest_name, nt_status);
+
+done:
+ if (gc) {
+ talloc_free(gc);
+ }
+
+ return nt_status;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+ NTSTATUS cell_locate_membership(ADS_STRUCT * ads)
+{
+ ADS_STATUS status;
+ char *domain_dn = ads_build_dn(lp_realm());
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID sid;
+ struct likewise_cell *cell = NULL;
+
+ /* In the Likewise plugin, I had to support the concept of cells
+ based on the machine's membership in an OU. However, now I'll
+ just assume our membership in the forest cell */
+
+ DEBUG(2, ("locate_cell_membership: Located membership "
+ "in cell \"%s\"\n", domain_dn));
+
+ if ((cell = cell_new()) == NULL) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ status = ads_domain_sid(ads, &sid);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(3,("locate_cell_membership: Failed to find "
+ "domain SID for %s\n", domain_dn));
+ }
+
+ /* save the SID and search base for our domain */
+
+ cell_set_dns_domain(cell, lp_realm());
+ cell_set_connection(cell, ads);
+ cell_set_dn(cell, domain_dn);
+ cell_set_domain_sid(cell, &sid);
+
+ /* Now save our forest root */
+
+ cell_lookup_forest(cell);
+
+ /* Add the cell to the list */
+
+ if (!cell_list_add(cell)) {
+ nt_status = NT_STATUS_INSUFFICIENT_RESOURCES;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Done! */
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0,("LWI: Failed to locate cell membership (%s)\n",
+ nt_errstr(nt_status)));
+ }
+
+ SAFE_FREE(domain_dn);
+
+ return nt_status;
+}
+
+/*********************************************************************
+ ********************************************************************/
+
+ int min_id_value(void)
+{
+ int id_val;
+
+ id_val = lp_parm_int(-1, "lwidentity", "min_id_value", MIN_ID_VALUE);
+
+ /* Still don't let it go below 50 */
+
+ return MAX(50, id_val);
+}
+
+/********************************************************************
+ *******************************************************************/
+
+ char *cell_dn_to_dns(const char *dn)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ char *domain = NULL;
+ char *dns_name = NULL;
+ const char *tmp_dn;
+ char *buffer = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ if (!dn || !*dn) {
+ goto done;
+ }
+
+ tmp_dn = talloc_strdup(frame, dn);
+ BAIL_ON_PTR_ERROR(tmp_dn, nt_status);
+
+ while (next_token_talloc(frame, &tmp_dn, &buffer, ",")) {
+
+ /* skip everything up the where DC=... begins */
+ if (StrnCaseCmp(buffer, "DC=", 3) != 0)
+ continue;
+
+ if (!domain) {
+ domain = talloc_strdup(frame, &buffer[3]);
+ } else {
+ domain = talloc_asprintf_append(domain, ".%s",
+ &buffer[3]);
+ }
+ BAIL_ON_PTR_ERROR(domain, nt_status);
+ }
+
+ dns_name = SMB_STRDUP(domain);
+ BAIL_ON_PTR_ERROR(dns_name, nt_status);
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ PRINT_NTSTATUS_ERROR(nt_status, "cell_dn_to_dns", 1);
+
+ talloc_destroy(frame);
+
+ return dns_name;
+}
+
+/*********************************************************************
+ ********************************************************************/
+
+ NTSTATUS get_sid_type(ADS_STRUCT *ads,
+ LDAPMessage *msg,
+ enum lsa_SidType *type)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32_t atype;
+
+ if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) {
+ nt_status = NT_STATUS_INVALID_USER_BUFFER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ switch (atype &0xF0000000) {
+ case ATYPE_SECURITY_GLOBAL_GROUP:
+ *type = SID_NAME_DOM_GRP;
+ break;
+ case ATYPE_SECURITY_LOCAL_GROUP:
+ *type = SID_NAME_ALIAS;
+ break;
+ case ATYPE_NORMAL_ACCOUNT:
+ case ATYPE_WORKSTATION_TRUST:
+ case ATYPE_INTERDOMAIN_TRUST:
+ *type = SID_NAME_USER;
+ break;
+ default:
+ *type = SID_NAME_USE_NONE;
+ nt_status = NT_STATUS_INVALID_ACCOUNT_NAME;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ return nt_status;
+}
diff --git a/source3/winbindd/idmap_adex/domain_util.c b/source3/winbindd/idmap_adex/domain_util.c
new file mode 100644
index 0000000000..ab31ccef7a
--- /dev/null
+++ b/source3/winbindd/idmap_adex/domain_util.c
@@ -0,0 +1,278 @@
+/*
+ * idmap_adex: Domain search interface
+ *
+ * Copyright (C) Gerald (Jerry) Carter 2007-2008
+ *
+ * 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 "idmap_adex.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+struct dc_info {
+ struct dc_info *prev, *next;
+ char *dns_name;
+ struct likewise_cell *domain_cell;
+};
+
+static struct dc_info *_dc_server_list = NULL;
+
+
+/**********************************************************************
+ *********************************************************************/
+
+static struct dc_info *dc_list_head(void)
+{
+ return _dc_server_list;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS dc_add_domain(const char *domain)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct dc_info *dc = NULL;
+
+ /* Check for duplicates */
+
+ dc = dc_list_head();
+ while (dc) {
+ if (strequal (dc->dns_name, domain))
+ break;
+ dc = dc->next;
+ }
+
+ if (dc) {
+ DEBUG(10,("dc_add_domain: %s already in list\n", domain));
+ return NT_STATUS_OK;
+ }
+
+ dc = TALLOC_ZERO_P(NULL, struct dc_info);
+ BAIL_ON_PTR_ERROR(dc, nt_status);
+
+ dc->dns_name = talloc_strdup(dc, domain);
+ BAIL_ON_PTR_ERROR(dc->dns_name, nt_status);
+
+ DLIST_ADD_END(_dc_server_list, dc, struct dc_info*);
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_destroy(dc);
+ DEBUG(0,("LWI: Failed to add new DC connection for %s (%s)\n",
+ domain, nt_errstr(nt_status)));
+ }
+
+ return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static void dc_server_list_destroy(void)
+{
+ struct dc_info *dc = dc_list_head();
+
+ while (dc) {
+ struct dc_info *p = dc->next;
+
+ cell_destroy(dc->domain_cell);
+ talloc_destroy(dc);
+
+ dc = p;
+ }
+
+ return;
+}
+
+
+/**********************************************************************
+ *********************************************************************/
+
+ NTSTATUS domain_init_list(void)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct winbindd_tdc_domain *domains = NULL;
+ size_t num_domains = 0;
+ int i;
+
+ if (_dc_server_list != NULL) {
+ dc_server_list_destroy();
+ }
+
+ /* Add our domain */
+
+ nt_status = dc_add_domain(lp_realm());
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ if (!wcache_tdc_fetch_list(&domains, &num_domains)) {
+ nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Add all domains with an incoming trust path */
+
+ for (i=0; i<num_domains; i++) {
+ uint32_t flags = (NETR_TRUST_FLAG_INBOUND|NETR_TRUST_FLAG_IN_FOREST);
+
+ /* We just require one of the flags to be set here */
+
+ if (domains[i].trust_flags & flags) {
+ nt_status = dc_add_domain(domains[i].dns_name);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(2,("LWI: Failed to initialize DC list (%s)\n",
+ nt_errstr(nt_status)));
+ }
+
+ TALLOC_FREE(domains);
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS dc_do_search(struct dc_info *dc,
+ const char *search_base,
+ int scope,
+ const char *expr,
+ const char **attrs,
+ LDAPMessage ** msg)
+{
+ ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ status = cell_do_search(dc->domain_cell, search_base,
+ scope, expr, attrs, msg);
+ nt_status = ads_ntstatus(status);
+
+ return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static struct dc_info *dc_find_domain(const char *dns_domain)
+{
+ struct dc_info *dc = dc_list_head();
+
+ if (!dc)
+ return NULL;
+
+ while (dc) {
+ if (strequal(dc->dns_name, dns_domain)) {
+ return dc;
+ }
+
+ dc = dc->next;
+ }
+
+ return NULL;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ NTSTATUS dc_search_domains(struct likewise_cell **cell,
+ LDAPMessage **msg,
+ const char *dn,
+ const DOM_SID *sid)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *dns_domain;
+ const char *attrs[] = { "*", NULL };
+ struct dc_info *dc = NULL;
+ const char *base = NULL;
+
+ if (!dn || !*dn) {
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ dns_domain = cell_dn_to_dns(dn);
+ BAIL_ON_PTR_ERROR(dns_domain, nt_status);
+
+ if ((dc = dc_find_domain(dns_domain)) == NULL) {
+ nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Reparse the cell settings for the domain if necessary */
+
+ if (!dc->domain_cell) {
+ char *base_dn;
+
+ base_dn = ads_build_dn(dc->dns_name);
+ BAIL_ON_PTR_ERROR(base_dn, nt_status);
+
+ nt_status = cell_connect_dn(&dc->domain_cell, base_dn);
+ SAFE_FREE(base_dn);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = cell_lookup_settings(dc->domain_cell);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* By definition this is already part of a larger
+ forest-wide search scope */
+
+ cell_set_flags(dc->domain_cell, LWCELL_FLAG_SEARCH_FOREST);
+ }
+
+ /* Check whether we are operating in non-schema or RFC2307
+ mode */
+
+ if (cell_flags(dc->domain_cell) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
+ nt_status = dc_do_search(dc, dn, LDAP_SCOPE_BASE,
+ "(objectclass=*)", attrs, msg);
+ } else {
+ const char *sid_str = NULL;
+ char *filter = NULL;
+
+ sid_str = sid_string_talloc(frame, sid);
+ BAIL_ON_PTR_ERROR(sid_str, nt_status);
+
+ filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
+ sid_str);
+ BAIL_ON_PTR_ERROR(filter, nt_status);
+
+ base = cell_search_base(dc->domain_cell);
+ BAIL_ON_PTR_ERROR(base, nt_status);
+
+ nt_status = dc_do_search(dc, base, LDAP_SCOPE_SUBTREE,
+ filter, attrs, msg);
+ }
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ *cell = dc->domain_cell;
+
+done:
+ talloc_destroy(CONST_DISCARD(char*, base));
+ talloc_destroy(frame);
+
+ return nt_status;
+}
diff --git a/source3/winbindd/idmap_adex/gc_util.c b/source3/winbindd/idmap_adex/gc_util.c
new file mode 100644
index 0000000000..87dd3c058d
--- /dev/null
+++ b/source3/winbindd/idmap_adex/gc_util.c
@@ -0,0 +1,848 @@
+/*
+ * idmap_adex: Global Catalog search interface
+ *
+ * Copyright (C) Gerald (Jerry) Carter 2007-2008
+ *
+ * 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 "idmap_adex.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+static struct gc_info *_gc_server_list = NULL;
+
+
+/**********************************************************************
+ *********************************************************************/
+
+static struct gc_info *gc_list_head(void)
+{
+ return _gc_server_list;
+}
+
+/**********************************************************************
+ Checks if either of the domains is a subdomain of the other
+ *********************************************************************/
+
+static bool is_subdomain(const char* a, const char *b)
+{
+ char *s;
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *x, *y;
+ bool ret = false;
+
+ /* Trivial cases */
+
+ if (!a && !b)
+ return true;
+
+ if (!a || !b)
+ return false;
+
+ /* Normalize the case */
+
+ x = talloc_strdup(frame, a);
+ y = talloc_strdup(frame, b);
+ if (!x || !y) {
+ ret = false;
+ goto done;
+ }
+
+ strupper_m(x);
+ strupper_m(y);
+
+ /* Exact match */
+
+ if (strcmp(x, y) == 0) {
+ ret = true;
+ goto done;
+ }
+
+ /* Check for trailing substrings */
+
+ s = strstr_m(x, y);
+ if (s && (strlen(s) == strlen(y))) {
+ ret = true;
+ goto done;
+ }
+
+ s = strstr_m(y, x);
+ if (s && (strlen(s) == strlen(x))) {
+ ret = true;
+ goto done;
+ }
+
+done:
+ talloc_destroy(frame);
+
+ return ret;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ NTSTATUS gc_find_forest_root(struct gc_info *gc, const char *domain)
+{
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS ads_status;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct nbt_cldap_netlogon_5 cldap_reply;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ if (!gc || !domain) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCT(cldap_reply);
+
+ ads = ads_init(domain, NULL, NULL);
+ BAIL_ON_PTR_ERROR(ads, nt_status);
+
+ ads->auth.flags = ADS_AUTH_NO_BIND;
+ ads_status = ads_connect(ads);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4, ("find_forest_root: ads_connect(%s) failed! (%s)\n",
+ domain, ads_errstr(ads_status)));
+ }
+ nt_status = ads_ntstatus(ads_status);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ if (!ads_cldap_netlogon_5(frame,
+ ads->config.ldap_server_name,
+ ads->config.realm,
+ &cldap_reply))
+ {
+ DEBUG(4,("find_forest_root: Failed to get a CLDAP reply from %s!\n",
+ ads->server.ldap_server));
+ nt_status = NT_STATUS_IO_TIMEOUT;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ gc->forest_name = talloc_strdup(gc, cldap_reply.forest);
+ BAIL_ON_PTR_ERROR(gc->forest_name, nt_status);
+
+done:
+ if (ads) {
+ ads_destroy(&ads);
+ }
+
+ return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS gc_add_forest(const char *domain)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct gc_info *gc = NULL;
+ struct gc_info *find_gc = NULL;
+ char *dn;
+ ADS_STRUCT *ads = NULL;
+ struct likewise_cell *primary_cell = NULL;
+
+ primary_cell = cell_list_head();
+ if (!primary_cell) {
+ nt_status = NT_STATUS_INVALID_SERVER_STATE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Check for duplicates based on domain name first as this
+ requires no connection */
+
+ find_gc = gc_list_head();
+ while (find_gc) {
+ if (strequal (find_gc->forest_name, domain))
+ break;
+ find_gc = find_gc->next;
+ }
+
+ if (find_gc) {
+ DEBUG(10,("gc_add_forest: %s already in list\n", find_gc->forest_name));
+ return NT_STATUS_OK;
+ }
+
+ if ((gc = TALLOC_ZERO_P(NULL, struct gc_info)) == NULL) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Query the rootDSE for the forest root naming conect first.
+ Check that the a GC server for the forest has not already
+ been added */
+
+ nt_status = gc_find_forest_root(gc, domain);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ find_gc = gc_list_head();
+ while (find_gc) {
+ if (strequal (find_gc->forest_name, gc->forest_name))
+ break;
+ find_gc = find_gc->next;
+ }
+
+ if (find_gc) {
+ DEBUG(10,("gc_add_forest: Forest %s already in list\n",
+ find_gc->forest_name));
+ return NT_STATUS_OK;
+ }
+
+ /* Not found, so add it here. Make sure we connect to
+ a DC in _this_ domain and not the forest root. */
+
+ dn = ads_build_dn(gc->forest_name);
+ BAIL_ON_PTR_ERROR(dn, nt_status);
+
+ gc->search_base = talloc_strdup(gc, dn);
+ SAFE_FREE(dn);
+ BAIL_ON_PTR_ERROR(gc->search_base, nt_status);
+
+#if 0
+ /* Can't use cell_connect_dn() here as there is no way to
+ specifiy the LWCELL_FLAG_GC_CELL flag setting for cell_connect() */
+
+ nt_status = cell_connect_dn(&gc->forest_cell, gc->search_base);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+#else
+
+ gc->forest_cell = cell_new();
+ BAIL_ON_PTR_ERROR(gc->forest_cell, nt_status);
+
+ /* Set the DNS domain, dn, etc ... and add it to the list */
+
+ cell_set_dns_domain(gc->forest_cell, gc->forest_name);
+ cell_set_dn(gc->forest_cell, gc->search_base);
+ cell_set_flags(gc->forest_cell, LWCELL_FLAG_GC_CELL);
+#endif
+
+ /* It is possible to belong to a non-forest cell and a
+ non-provisioned forest (at our domain levele). In that
+ case, we should just inherit the flags from our primary
+ cell since the GC searches will match our own schema
+ model. */
+
+ if (strequal(primary_cell->forest_name, gc->forest_name)
+ || is_subdomain(primary_cell->dns_domain, gc->forest_name))
+ {
+ cell_set_flags(gc->forest_cell, cell_flags(primary_cell));
+ } else {
+ /* outside of our domain */
+
+ nt_status = cell_connect(gc->forest_cell);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = cell_lookup_settings(gc->forest_cell);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* Drop the connection now that we have the settings */
+
+ ads = cell_connection(gc->forest_cell);
+ ads_destroy(&ads);
+ cell_set_connection(gc->forest_cell, NULL);
+ }
+
+ DLIST_ADD_END(_gc_server_list, gc, struct gc_info*);
+
+ DEBUG(10,("gc_add_forest: Added %s to Global Catalog list of servers\n",
+ gc->forest_name));
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_destroy(gc);
+ DEBUG(3,("LWI: Failed to add new GC connection for %s (%s)\n",
+ domain, nt_errstr(nt_status)));
+ }
+
+ return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static void gc_server_list_destroy(void)
+{
+ struct gc_info *gc = gc_list_head();
+
+ while (gc) {
+ struct gc_info *p = gc->next;
+
+ cell_destroy(gc->forest_cell);
+ talloc_destroy(gc);
+
+ gc = p;
+ }
+
+ _gc_server_list = NULL;
+
+ return;
+}
+
+/**********************************************************************
+ Setup the initial list of forests and initial the forest cell
+ settings for each. FIXME!!!
+ *********************************************************************/
+
+ NTSTATUS gc_init_list(void)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct winbindd_tdc_domain *domains = NULL;
+ size_t num_domains = 0;
+ int i;
+
+ if (_gc_server_list != NULL) {
+ gc_server_list_destroy();
+ }
+
+ if (!wcache_tdc_fetch_list(&domains, &num_domains)) {
+ nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Find our forest first. Have to try all domains here starting
+ with our own. gc_add_forest() filters duplicates */
+
+ nt_status = gc_add_forest(lp_realm());
+ WARN_ON_NTSTATUS_ERROR(nt_status);
+
+ for (i=0; i<num_domains; i++) {
+ uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST);
+
+ /* I think we should be able to break out of loop once
+ we add a GC for our forest and not have to test every one.
+ In fact, this entire loop is probably irrelevant since
+ the GC location code should always find a GC given lp_realm().
+ Will have to spend time testing before making the change.
+ --jerry */
+
+ if ((domains[i].trust_flags & flags) == flags) {
+ nt_status = gc_add_forest(domains[i].dns_name);
+ WARN_ON_NTSTATUS_ERROR(nt_status);
+ /* Don't BAIL here since not every domain may
+ have a GC server */
+ }
+ }
+
+ /* Now add trusted forests. gc_add_forest() will filter out
+ duplicates. Check everything with an incoming trust path
+ that is not in our own forest. */
+
+ for (i=0; i<num_domains; i++) {
+ uint32_t flags = domains[i].trust_flags;
+ uint32_t attribs = domains[i].trust_attribs;
+
+ /* Skip non_AD domains */
+
+ if (strlen(domains[i].dns_name) == 0) {
+ continue;
+ }
+
+ /* Only add a GC for a forest outside of our own.
+ Ignore QUARANTINED/EXTERNAL trusts */
+
+ if ((flags & NETR_TRUST_FLAG_INBOUND)
+ && !(flags & NETR_TRUST_FLAG_IN_FOREST)
+ && (attribs & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
+ {
+ nt_status = gc_add_forest(domains[i].dns_name);
+ WARN_ON_NTSTATUS_ERROR(nt_status);
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(2,("LWI: Failed to initialized GC list (%s)\n",
+ nt_errstr(nt_status)));
+ }
+
+ TALLOC_FREE(domains);
+
+ return nt_status;
+}
+
+
+/**********************************************************************
+ *********************************************************************/
+
+ struct gc_info *gc_search_start(void)
+{
+ NTSTATUS nt_status = NT_STATUS_OK;
+ struct gc_info *gc = gc_list_head();
+
+ if (!gc) {
+ nt_status = gc_init_list();
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ gc = gc_list_head();
+ }
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(2,("LWI: Failed to initialize GC list (%s)\n",
+ nt_errstr(nt_status)));
+ }
+
+ return gc;
+}
+
+/**********************************************************************
+ Search Global Catalog. Always search our own forest. The flags set
+ controls whether or not we search cross forest. Assume that the
+ resulting set is always returned from one GC so that we don't have to
+ both combining the LDAPMessage * results
+ *********************************************************************/
+
+ NTSTATUS gc_search_forest(struct gc_info *gc,
+ LDAPMessage **msg,
+ const char *filter)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+ const char *attrs[] = {"*", NULL};
+ LDAPMessage *m = NULL;
+
+ if (!gc || !msg || !filter) {
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* When you have multiple domain trees in a forest, the
+ GC will search all naming contexts when you send it
+ and empty ("") base search suffix. Tested against
+ Windows 2003. */
+
+ ads_status = cell_do_search(gc->forest_cell, "",
+ LDAP_SCOPE_SUBTREE, filter, attrs, &m);
+ nt_status = ads_ntstatus(ads_status);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ *msg = m;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(2,("LWI: Forest wide search %s failed (%s)\n",
+ filter, nt_errstr(nt_status)));
+ }
+
+ return nt_status;
+}
+
+/**********************************************************************
+ Search all forests via GC and return the results in an array of
+ ADS_STRUCT/LDAPMessage pairs.
+ *********************************************************************/
+
+ NTSTATUS gc_search_all_forests(const char *filter,
+ ADS_STRUCT ***ads_list,
+ LDAPMessage ***msg_list,
+ int *num_resp, uint32_t flags)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct gc_info *gc = NULL;
+ uint32_t test_flags = ADEX_GC_SEARCH_CHECK_UNIQUE;
+
+ *ads_list = NULL;
+ *msg_list = NULL;
+ *num_resp = 0;
+
+ if ((gc = gc_search_start()) == NULL) {
+ nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ while (gc) {
+ LDAPMessage *m = NULL;
+
+ nt_status = gc_search_forest(gc, &m, filter);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ gc = gc->next;
+ continue;
+ }
+
+ nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
+ m, ads_list, msg_list,
+ num_resp);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* If there can only be one match, then we are done */
+
+ if ((*num_resp > 0) && ((flags & test_flags) == test_flags)) {
+ break;
+ }
+
+ gc = gc->next;
+ }
+
+ if (*num_resp == 0) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ return nt_status;
+}
+
+/**********************************************************************
+ Search all forests via GC and return the results in an array of
+ ADS_STRUCT/LDAPMessage pairs.
+ *********************************************************************/
+
+ NTSTATUS gc_search_all_forests_unique(const char *filter,
+ ADS_STRUCT **ads,
+ LDAPMessage **msg)
+{
+ ADS_STRUCT **ads_list = NULL;
+ LDAPMessage **msg_list = NULL;
+ int num_resp;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ nt_status = gc_search_all_forests(filter, &ads_list,
+ &msg_list, &num_resp,
+ ADEX_GC_SEARCH_CHECK_UNIQUE);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = check_result_unique(ads_list[0], msg_list[0]);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ *ads = ads_list[0];
+ *msg = msg_list[0];
+
+done:
+ /* Be care that we don't free the msg result being returned */
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ free_result_array(ads_list, msg_list, num_resp);
+ } else {
+ talloc_destroy(ads_list);
+ talloc_destroy(msg_list);
+ }
+
+ return nt_status;
+}
+
+/*********************************************************************
+ ********************************************************************/
+
+ NTSTATUS gc_name_to_sid(const char *domain,
+ const char *name,
+ DOM_SID *sid,
+ enum lsa_SidType *sid_type)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *p, *name_user;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ char *name_filter;
+ ADS_STRUCT *ads = NULL;
+ LDAPMessage *msg = NULL;
+ LDAPMessage *e = NULL;
+ char *dn = NULL;
+ char *dns_domain = NULL;
+ ADS_STRUCT **ads_list = NULL;
+ LDAPMessage **msg_list = NULL;
+ int num_resp = 0;
+ int i;
+
+ /* Strip the "DOMAIN\" prefix if necessary and search for
+ a matching sAMAccountName in the forest */
+
+ if ((p = strchr_m( name, '\\' )) == NULL)
+ name_user = talloc_strdup( frame, name );
+ else
+ name_user = talloc_strdup( frame, p+1 );
+ BAIL_ON_PTR_ERROR(name_user, nt_status);
+
+ name_filter = talloc_asprintf(frame, "(sAMAccountName=%s)", name_user);
+ BAIL_ON_PTR_ERROR(name_filter, nt_status);
+
+ nt_status = gc_search_all_forests(name_filter, &ads_list,
+ &msg_list, &num_resp, 0);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* Assume failure until we know otherwise*/
+
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ /* Match the domain name from the DN */
+
+ for (i=0; i<num_resp; i++) {
+ ads = ads_list[i];
+ msg = msg_list[i];
+
+ e = ads_first_entry(ads, msg);
+ while (e) {
+ struct winbindd_tdc_domain *domain_rec;
+
+ dn = ads_get_dn(ads, e);
+ BAIL_ON_PTR_ERROR(dn, nt_status);
+
+ dns_domain = cell_dn_to_dns(dn);
+ SAFE_FREE(dn);
+ BAIL_ON_PTR_ERROR(dns_domain, nt_status);
+
+ domain_rec = wcache_tdc_fetch_domain(frame, dns_domain);
+ SAFE_FREE(dns_domain);
+
+ /* Ignore failures and continue the search */
+
+ if (!domain_rec) {
+ e = ads_next_entry(ads, e);
+ continue;
+ }
+
+ /* Check for a match on the domain name */
+
+ if (strequal(domain, domain_rec->domain_name)) {
+ if (!ads_pull_sid(ads, e, "objectSid", sid)) {
+ nt_status = NT_STATUS_INVALID_SID;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ talloc_destroy(domain_rec);
+
+ nt_status = get_sid_type(ads, msg, sid_type);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* We're done! */
+ nt_status = NT_STATUS_OK;
+ break;
+ }
+
+ /* once more around thew merry-go-round */
+
+ talloc_destroy(domain_rec);
+ e = ads_next_entry(ads, e);
+ }
+ }
+
+done:
+ free_result_array(ads_list, msg_list, num_resp);
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/********************************************************************
+ Pull an attribute string value
+ *******************************************************************/
+
+static NTSTATUS get_object_account_name(ADS_STRUCT *ads,
+ LDAPMessage *msg,
+ char **name)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ char *sam_name = NULL;
+ struct winbindd_tdc_domain *domain_rec = NULL;
+ char *dns_domain = NULL;
+ char *dn = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ int len;
+
+ /* Check parameters */
+
+ if (!ads || !msg || !name) {
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* get the name and domain */
+
+ dn = ads_get_dn(ads, msg);
+ BAIL_ON_PTR_ERROR(dn, nt_status);
+
+ DEBUG(10,("get_object_account_name: dn = \"%s\"\n", dn));
+
+ dns_domain = cell_dn_to_dns(dn);
+ SAFE_FREE(dn);
+ BAIL_ON_PTR_ERROR(dns_domain, nt_status);
+
+ domain_rec = wcache_tdc_fetch_domain(frame, dns_domain);
+ SAFE_FREE(dns_domain);
+
+ if (!domain_rec) {
+ nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ sam_name = ads_pull_string(ads, frame, msg, "sAMAccountName");
+ BAIL_ON_PTR_ERROR(sam_name, nt_status);
+
+ len = asprintf(name, "%s\\%s", domain_rec->domain_name, sam_name);
+ if (len == -1) {
+ *name = NULL;
+ BAIL_ON_PTR_ERROR((*name), nt_status);
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/*********************************************************************
+ ********************************************************************/
+
+ NTSTATUS gc_sid_to_name(const DOM_SID *sid,
+ char **name,
+ enum lsa_SidType *sid_type)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ char *filter;
+ ADS_STRUCT *ads = NULL;
+ LDAPMessage *msg = NULL;
+ char *sid_string;
+
+ *name = NULL;
+
+ sid_string = sid_binstring(sid);
+ BAIL_ON_PTR_ERROR(sid_string, nt_status);
+
+ filter = talloc_asprintf(frame, "(objectSid=%s)", sid_string);
+ SAFE_FREE(sid_string);
+ BAIL_ON_PTR_ERROR(filter, nt_status);
+
+ nt_status = gc_search_all_forests_unique(filter, &ads, &msg);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = get_object_account_name(ads, msg, name);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = get_sid_type(ads, msg, sid_type);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+done:
+ ads_msgfree(ads, msg);
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ NTSTATUS add_ads_result_to_array(ADS_STRUCT *ads,
+ LDAPMessage *msg,
+ ADS_STRUCT ***ads_list,
+ LDAPMessage ***msg_list,
+ int *size)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ ADS_STRUCT **ads_tmp = NULL;
+ LDAPMessage **msg_tmp = NULL;
+ int count = *size;
+
+ if (!ads || !msg) {
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+#if 0
+ /* Don't add a response with no entries */
+
+ if (ads_count_replies(ads, msg) == 0) {
+ return NT_STATUS_OK;
+ }
+#endif
+
+ if (count == 0) {
+ ads_tmp = TALLOC_ARRAY(NULL, ADS_STRUCT*, 1);
+ BAIL_ON_PTR_ERROR(ads_tmp, nt_status);
+
+ msg_tmp = TALLOC_ARRAY(NULL, LDAPMessage*, 1);
+ BAIL_ON_PTR_ERROR(msg_tmp, nt_status);
+ } else {
+ ads_tmp = TALLOC_REALLOC_ARRAY(*ads_list, *ads_list, ADS_STRUCT*,
+ count+1);
+ BAIL_ON_PTR_ERROR(ads_tmp, nt_status);
+
+ msg_tmp = TALLOC_REALLOC_ARRAY(*msg_list, *msg_list, LDAPMessage*,
+ count+1);
+ BAIL_ON_PTR_ERROR(msg_tmp, nt_status);
+ }
+
+ ads_tmp[count] = ads;
+ msg_tmp[count] = msg;
+ count++;
+
+ *ads_list = ads_tmp;
+ *msg_list = msg_tmp;
+ *size = count;
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_destroy(ads_tmp);
+ talloc_destroy(msg_tmp);
+ }
+
+ return nt_status;
+}
+
+/**********************************************************************
+ Frees search results. Do not free the ads_list as these are
+ references back to the GC search structures.
+ *********************************************************************/
+
+ void free_result_array(ADS_STRUCT **ads_list,
+ LDAPMessage **msg_list,
+ int num_resp)
+{
+ int i;
+
+ for (i=0; i<num_resp; i++) {
+ ads_msgfree(ads_list[i], msg_list[i]);
+ }
+
+ talloc_destroy(ads_list);
+ talloc_destroy(msg_list);
+}
+
+/**********************************************************************
+ Check that we have exactly one entry from the search
+ *********************************************************************/
+
+ NTSTATUS check_result_unique(ADS_STRUCT *ads, LDAPMessage *msg)
+{
+ NTSTATUS nt_status;
+ int count;
+
+ count = ads_count_replies(ads, msg);
+
+ if (count <= 0) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ if (count > 1) {
+ nt_status = NT_STATUS_DUPLICATE_NAME;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ return nt_status;
+}
diff --git a/source3/winbindd/idmap_adex/idmap_adex.c b/source3/winbindd/idmap_adex/idmap_adex.c
new file mode 100644
index 0000000000..23ab843e95
--- /dev/null
+++ b/source3/winbindd/idmap_adex/idmap_adex.c
@@ -0,0 +1,460 @@
+/*
+ * idmap_adex: Support for D Forests
+ *
+ * Copyright (C) Gerald (Jerry) Carter 2006-2008
+ *
+ * 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 "idmap_adex.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
+
+NTSTATUS init_module(void);
+
+/*
+ * IdMap backend
+ */
+
+/********************************************************************
+ Basic init function responsible for determining our current mode
+ (standalone or using Centeris Cells). This must return success or
+ it will be dropped from the idmap backend list.
+ *******************************************************************/
+
+static NTSTATUS _idmap_adex_init(struct idmap_domain *dom,
+ const char *params)
+{
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+ DOM_SID domain_sid;
+ fstring dcname;
+ struct sockaddr_storage ip;
+ struct likewise_cell *lwcell;
+
+ if (NT_STATUS_IS_OK(init_status))
+ return NT_STATUS_OK;
+
+ /* Silently fail if we are not a member server in security = ads */
+
+ if ((lp_server_role() != ROLE_DOMAIN_MEMBER) ||
+ (lp_security() != SEC_ADS)) {
+ init_status = NT_STATUS_INVALID_SERVER_STATE;
+ BAIL_ON_NTSTATUS_ERROR(init_status);
+ }
+
+ /* fetch our domain SID first */
+
+ if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
+ init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ BAIL_ON_NTSTATUS_ERROR(init_status);
+ }
+
+ /* reuse the same ticket cache as winbindd */
+
+ setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
+
+ /* Establish a connection to a DC */
+
+ if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) {
+ init_status = NT_STATUS_NO_MEMORY;
+ BAIL_ON_NTSTATUS_ERROR(init_status);
+ }
+
+ ads->auth.password =
+ secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+ ads->auth.realm = SMB_STRDUP(lp_realm());
+
+ /* get the DC name here to setup the server affinity cache and
+ local krb5.conf */
+
+ get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip);
+
+ status = ads_connect(ads);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n",
+ ads_errstr(status)));
+ }
+ init_status = ads_ntstatus(status);
+ BAIL_ON_NTSTATUS_ERROR(init_status);
+
+
+ /* Find out cell membership */
+
+ init_status = cell_locate_membership(ads);
+ if (!NT_STATUS_IS_OK(init_status)) {
+ DEBUG(0,("LWI: Fail to locate cell membership (%s).",
+ nt_errstr(init_status)));
+ goto done;
+ }
+
+ /* Fill in the cell information */
+
+ lwcell = cell_list_head();
+
+ init_status = cell_lookup_settings(lwcell);
+ BAIL_ON_NTSTATUS_ERROR(init_status);
+
+ /* Miscellaneous setup. E.g. set up the list of GC
+ servers and domain list for our forest (does not actually
+ connect). */
+
+ init_status = gc_init_list();
+ BAIL_ON_NTSTATUS_ERROR(init_status);
+
+ init_status = domain_init_list();
+ BAIL_ON_NTSTATUS_ERROR(init_status);
+
+done:
+ if (!NT_STATUS_IS_OK(init_status)) {
+ DEBUG(1,("Likewise initialization failed (%s)\n",
+ nt_errstr(init_status)));
+ }
+
+ /* cleanup */
+
+ if (!NT_STATUS_IS_OK(init_status)) {
+ cell_list_destroy();
+
+ /* init_status stores the failure reason but we need to
+ return success or else idmap_init() will drop us from the
+ backend list */
+ return NT_STATUS_OK;
+ }
+
+ init_status = NT_STATUS_OK;
+
+ return init_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _idmap_adex_get_sid_from_id(struct
+ idmap_domain
+ *dom, struct
+ id_map
+ **ids)
+{
+ int i;
+ bool one_mapped = false;
+ bool all_mapped = true;
+ NTSTATUS nt_status;
+ struct likewise_cell *cell;
+
+ nt_status = _idmap_adex_init(dom, NULL);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ if ((cell = cell_list_head()) == NULL) {
+ return NT_STATUS_INVALID_SERVER_STATE;
+ }
+
+ /* have to work through these one by one */
+ for (i = 0; ids[i]; i++) {
+ NTSTATUS status;
+ status = cell->provider->get_sid_from_id(ids[i]->sid,
+ ids[i]->xid.id,
+ ids[i]->xid.type);
+ /* Fail if we cannot find any DC */
+ if (NT_STATUS_EQUAL
+ (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
+ return status;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ ids[i]->status = ID_UNMAPPED;
+ all_mapped = false;
+ continue;
+ }
+
+ ids[i]->status = ID_MAPPED;
+ one_mapped = true;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _idmap_adex_get_id_from_sid(struct
+ idmap_domain
+ *dom, struct
+ id_map
+ **ids)
+{
+ int i;
+ bool one_mapped = false;
+ bool all_mapped = true;
+ NTSTATUS nt_status;
+ struct likewise_cell *cell;
+
+ nt_status = _idmap_adex_init(dom, NULL);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ if ((cell = cell_list_head()) == NULL) {
+ return NT_STATUS_INVALID_SERVER_STATE;
+ }
+
+ /* have to work through these one by one */
+ for (i = 0; ids[i]; i++) {
+ NTSTATUS status;
+ status = cell->provider->get_id_from_sid(&ids[i]->xid.id,
+ &ids[i]->xid.
+ type, ids[i]->sid);
+ /* Fail if we cannot find any DC */
+ if (NT_STATUS_EQUAL
+ (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
+ return status;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ ids[i]->status = ID_UNMAPPED;
+ all_mapped = false;
+ continue;
+ }
+
+ ids[i]->status = ID_MAPPED;
+ one_mapped = true;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _idmap_adex_set_mapping(struct
+ idmap_domain
+ *dom, const struct
+ id_map *map)
+{
+ DEBUG(0, ("_idmap_adex_set_mapping: not implemented\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _idmap_adex_remove_mapping(struct
+ idmap_domain
+ *dom, const
+ struct
+ id_map
+ *map)
+{
+ DEBUG(0, ("_idmap_adex_remove_mapping: not implemented\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _idmap_adex_dump(struct idmap_domain
+ *dom, struct id_map **maps, int *num_map)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _idmap_adex_close(struct idmap_domain
+ *dom)
+{
+ /* FIXME! need to do cleanup here */
+
+ return NT_STATUS_OK;
+}
+
+/*
+ * IdMap NSS plugin
+ */
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _nss_adex_init(struct nss_domain_entry
+ *e)
+{
+ return _idmap_adex_init(NULL, NULL);
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _nss_adex_get_info(struct
+ nss_domain_entry *e,
+ const DOM_SID * sid,
+ TALLOC_CTX * ctx,
+ ADS_STRUCT * ads,
+ LDAPMessage * msg,
+ char **homedir,
+ char **shell, char **gecos, gid_t * p_gid)
+{
+ NTSTATUS nt_status;
+ struct likewise_cell *cell;
+
+ nt_status = _idmap_adex_init(NULL, NULL);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ if ((cell = cell_list_head()) == NULL) {
+ return NT_STATUS_INVALID_SERVER_STATE;
+ }
+
+ return cell->provider->get_nss_info(sid, ctx, homedir,
+ shell, gecos, p_gid);
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _nss_adex_map_to_alias(TALLOC_CTX * mem_ctx, const char
+ *domain, const char
+ *name, char **alias)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct likewise_cell *cell = NULL;
+
+ nt_status = _idmap_adex_init(NULL, NULL);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ if ((cell = cell_list_head()) == NULL) {
+ nt_status = NT_STATUS_INVALID_SERVER_STATE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ nt_status = cell->provider->map_to_alias(mem_ctx, domain,
+ name, alias);
+
+ /* go ahead and allow the cache mgr to mark this in
+ negative cache */
+
+ if (!NT_STATUS_IS_OK(nt_status))
+ nt_status = NT_STATUS_NONE_MAPPED;
+
+done:
+ return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _nss_adex_map_from_alias(TALLOC_CTX * mem_ctx, const char
+ *domain, const char
+ *alias, char **name)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct likewise_cell *cell = NULL;
+
+ nt_status = _idmap_adex_init(NULL, NULL);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ if ((cell = cell_list_head()) == NULL) {
+ nt_status = NT_STATUS_INVALID_SERVER_STATE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+
+ nt_status = cell->provider->map_from_alias(mem_ctx, domain,
+ alias, name);
+
+ /* go ahead and allow the cache mgr to mark this in
+ negative cache */
+
+ if (!NT_STATUS_IS_OK(nt_status))
+ nt_status = NT_STATUS_NONE_MAPPED;
+
+done:
+ return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _nss_adex_close(void)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static struct idmap_methods adex_idmap_methods = {
+
+ .init = _idmap_adex_init,
+ .unixids_to_sids = _idmap_adex_get_sid_from_id,
+ .sids_to_unixids = _idmap_adex_get_id_from_sid,
+ .set_mapping = _idmap_adex_set_mapping,
+ .remove_mapping = _idmap_adex_remove_mapping,
+ .dump_data = _idmap_adex_dump,
+ .close_fn = _idmap_adex_close
+};
+static struct nss_info_methods adex_nss_methods = {
+ .init = _nss_adex_init,
+ .get_nss_info = _nss_adex_get_info,
+ .map_to_alias = _nss_adex_map_to_alias,
+ .map_from_alias = _nss_adex_map_from_alias,
+ .close_fn = _nss_adex_close
+};
+
+/**********************************************************************
+ Register with the idmap and idmap_nss subsystems. We have to protect
+ against the idmap and nss_info interfaces being in a half-registered
+ state.
+ **********************************************************************/
+NTSTATUS idmap_adex_init(void)
+{
+ static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL;
+ static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL;
+ if (!NT_STATUS_IS_OK(idmap_status)) {
+ idmap_status =
+ smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
+ "adex", &adex_idmap_methods);
+ if (!NT_STATUS_IS_OK(idmap_status)) {
+ DEBUG(0,
+ ("idmap_centeris_init: Failed to register the adex"
+ "idmap plugin.\n"));
+ return idmap_status;
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(nss_status)) {
+ nss_status =
+ smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
+ "adex", &adex_nss_methods);
+ if (!NT_STATUS_IS_OK(nss_status)) {
+ DEBUG(0,
+ ("idmap_adex_init: Failed to register the adex"
+ "nss plugin.\n"));
+ return nss_status;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS nss_info_adex_init(void)
+{
+ return idmap_adex_init();
+}
diff --git a/source3/winbindd/idmap_adex/idmap_adex.h b/source3/winbindd/idmap_adex/idmap_adex.h
new file mode 100644
index 0000000000..f91bba8d07
--- /dev/null
+++ b/source3/winbindd/idmap_adex/idmap_adex.h
@@ -0,0 +1,257 @@
+/*
+ * idmap_centeris: Support for Local IDs and Centeris Cell Structure
+ *
+ * Copyright (C) Gerald (Jerry) Carter 2006-2008
+ *
+ * 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.
+ */
+
+#ifndef _IDMAP_ADEX_H
+#define _IDMAP_ADEX_H
+
+#include "winbindd/winbindd.h"
+
+#define ADEX_CELL_RDN "$LikewiseIdentityCell"
+
+#define ADEX_OC_USER "centerisLikewiseUser"
+#define ADEX_OC_GROUP "centerisLikewiseGroup"
+
+#define AD_USER "User"
+#define AD_GROUP "Group"
+
+#define ADEX_OC_POSIX_USER "posixAccount"
+#define ADEX_OC_POSIX_GROUP "posixGroup"
+
+#define ADEX_ATTR_UIDNUM "uidNumber"
+#define ADEX_ATTR_GIDNUM "gidNUmber"
+#define ADEX_ATTR_HOMEDIR "unixHomeDirectory"
+#define ADEX_ATTR_USERPW "unixUserPassword"
+#define ADEX_ATTR_GROUPALIAS "groupAlias" /* Not part of RFC2307 */
+#define ADEX_ATTR_SHELL "loginShell"
+#define ADEX_ATTR_GECOS "gecos"
+#define ADEX_ATTR_UID "uid"
+#define ADEX_ATTR_DISPLAYNAME "displayName"
+
+#define MIN_ID_VALUE 100
+
+#define BAIL_ON_NTSTATUS_ERROR(x) \
+ do { \
+ if (!NT_STATUS_IS_OK(x)) { \
+ DEBUG(10,("Failed! (%s)\n", nt_errstr(x))); \
+ goto done; \
+ } \
+ } \
+ while (0); \
+
+#define WARN_ON_NTSTATUS_ERROR(x) \
+ do { \
+ if (!NT_STATUS_IS_OK(x)) { \
+ DEBUG(10,("Failure ignored! (%s)\n", nt_errstr(x))); \
+ } \
+ } \
+ while (0); \
+
+#define BAIL_ON_ADS_ERROR(x) \
+ do { \
+ if (!ADS_ERR_OK(x)) { \
+ goto done; \
+ } \
+ } \
+ while (0);
+
+#define BAIL_ON_PTR_ERROR(p, x) \
+ do { \
+ if ((p) == NULL ) { \
+ DEBUG(10,("NULL pointer!\n")); \
+ x = NT_STATUS_NO_MEMORY; \
+ goto done; \
+ } \
+ } while (0);
+
+#define PRINT_NTSTATUS_ERROR(x, hdr, level) \
+ do { \
+ if (!NT_STATUS_IS_OK(x)) { \
+ DEBUG(level,("LWI ("hdr"): %s\n", nt_errstr(x))); \
+ } \
+ } while(0);
+/*
+ * Cell Provider API
+ */
+
+struct cell_provider_api {
+ NTSTATUS(*get_sid_from_id) (DOM_SID * sid,
+ uint32_t id, enum id_type type);
+ NTSTATUS(*get_id_from_sid) (uint32_t * id,
+ enum id_type * type, const DOM_SID * sid);
+ NTSTATUS(*get_nss_info) (const DOM_SID * sid,
+ TALLOC_CTX * ctx,
+ char **homedir,
+ char **shell, char **gecos, gid_t * p_gid);
+ NTSTATUS(*map_to_alias) (TALLOC_CTX * mem_ctx,
+ const char *domain,
+ const char *name, char **alias);
+ NTSTATUS(*map_from_alias) (TALLOC_CTX * mem_ctx,
+ const char *domain,
+ const char *alias, char **name);
+};
+
+/* registered providers */
+
+extern struct cell_provider_api ccp_unified;
+extern struct cell_provider_api ccp_local;
+
+#define LWCELL_FLAG_USE_RFC2307_ATTRS 0x00000001
+#define LWCELL_FLAG_SEARCH_FOREST 0x00000002
+#define LWCELL_FLAG_GC_CELL 0x00000004
+#define LWCELL_FLAG_LOCAL_MODE 0x00000008
+
+struct likewise_cell {
+ struct likewise_cell *prev, *next;
+ ADS_STRUCT *conn;
+ struct likewise_cell *gc_search_cell;
+ DOM_SID domain_sid;
+ char *dns_domain;
+ char *forest_name;
+ char *dn;
+ struct GUID *links; /* only held by owning cell */
+ size_t num_links;
+ uint32_t flags;
+ struct cell_provider_api *provider;
+};
+
+/* Search flags used for Global Catalog API */
+
+#define ADEX_GC_SEARCH_CHECK_UNIQUE 0x00000001
+
+struct gc_info {
+ struct gc_info *prev, *next;
+ char *forest_name;
+ char *search_base;
+ struct likewise_cell *forest_cell;
+};
+
+/* Available functions outside of idmap_lwidentity.c */
+
+/* cell_util.c */
+
+char *find_attr_string(char **list, size_t num_lines, const char *substr);
+bool is_object_class(char **list, size_t num_lines, const char *substr);
+int min_id_value(void);
+char *cell_dn_to_dns(const char *dn);
+NTSTATUS get_sid_type(ADS_STRUCT *ads,
+ LDAPMessage *msg,
+ enum lsa_SidType *type);
+
+NTSTATUS cell_locate_membership(ADS_STRUCT * ads);
+NTSTATUS cell_lookup_settings(struct likewise_cell * cell);
+NTSTATUS cell_follow_links(struct likewise_cell *cell);
+NTSTATUS cell_set_local_provider(void);
+
+/* likewise_cell.c */
+
+struct likewise_cell *cell_new(void);
+struct likewise_cell *cell_list_head(void);
+
+bool cell_list_add(struct likewise_cell *cell);
+bool cell_list_remove(struct likewise_cell * cell);
+
+void cell_list_destroy();
+void cell_destroy(struct likewise_cell *c);
+void cell_set_forest_searches(struct likewise_cell *c,
+ bool search);
+void cell_set_dns_domain(struct likewise_cell *c,
+ const char *dns_domain);
+void cell_set_connection(struct likewise_cell *c,
+ ADS_STRUCT *ads);
+void cell_set_dn(struct likewise_cell *c,
+ const char *dn);
+void cell_set_domain_sid(struct likewise_cell *c,
+ DOM_SID *sid);
+void cell_set_flags(struct likewise_cell *c, uint32_t flags);
+void cell_clear_flags(struct likewise_cell *c, uint32_t flags);
+
+const char* cell_search_base(struct likewise_cell *c);
+const char *cell_dns_domain(struct likewise_cell *c);
+ADS_STRUCT *cell_connection(struct likewise_cell *c);
+bool cell_search_forest(struct likewise_cell *c);
+ADS_STATUS cell_do_search(struct likewise_cell *c,
+ const char *search_base,
+ int scope,
+ const char *expr,
+ const char **attrs,
+ LDAPMessage ** msg);
+uint32_t cell_flags(struct likewise_cell *c);
+
+NTSTATUS cell_connect_dn(struct likewise_cell **c,
+ const char *dn);
+NTSTATUS cell_connect(struct likewise_cell *c);
+
+
+/* gc_util.c */
+
+NTSTATUS gc_init_list(void);
+
+NTSTATUS gc_find_forest_root(struct gc_info *gc,
+ const char *domain);
+
+struct gc_info *gc_search_start(void);
+
+NTSTATUS gc_search_forest(struct gc_info *gc,
+ LDAPMessage **msg,
+ const char *filter);
+
+NTSTATUS gc_search_all_forests(const char *filter,
+ ADS_STRUCT ***ads_list,
+ LDAPMessage ***msg_list,
+ int *num_resp, uint32_t flags);
+
+NTSTATUS gc_search_all_forests_unique(const char *filter,
+ ADS_STRUCT **ads,
+ LDAPMessage **msg);
+
+NTSTATUS gc_name_to_sid(const char *domain,
+ const char *name,
+ DOM_SID *sid,
+ enum lsa_SidType *sid_type);
+
+NTSTATUS gc_sid_to_name(const DOM_SID *sid,
+ char **name,
+ enum lsa_SidType *sid_type);
+
+NTSTATUS add_ads_result_to_array(ADS_STRUCT *ads,
+ LDAPMessage *msg,
+ ADS_STRUCT ***ads_list,
+ LDAPMessage ***msg_list,
+ int *size);
+
+void free_result_array(ADS_STRUCT **ads_list,
+ LDAPMessage **msg_list,
+ int num_resp);
+
+NTSTATUS check_result_unique(ADS_STRUCT *ads,
+ LDAPMessage *msg);
+
+
+/* domain_util.c */
+
+NTSTATUS domain_init_list(void);
+
+NTSTATUS dc_search_domains(struct likewise_cell **cell,
+ LDAPMessage **msg,
+ const char *dn,
+ const DOM_SID *user_sid);
+
+
+#endif /* _IDMAP_ADEX_H */
diff --git a/source3/winbindd/idmap_adex/likewise_cell.c b/source3/winbindd/idmap_adex/likewise_cell.c
new file mode 100644
index 0000000000..77eeee406b
--- /dev/null
+++ b/source3/winbindd/idmap_adex/likewise_cell.c
@@ -0,0 +1,425 @@
+/*
+ * idmap_adex: Support for AD Forests
+ *
+ * Copyright (C) Gerald (Jerry) Carter 2006-2008
+ *
+ * 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 "idmap_adex.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+static struct likewise_cell *_lw_cell_list = NULL;
+
+/**********************************************************************
+ Return the current HEAD of the list
+ *********************************************************************/
+
+ struct likewise_cell *cell_list_head(void)
+{
+ return _lw_cell_list;
+}
+
+
+/**********************************************************************
+ *********************************************************************/
+
+ void cell_destroy(struct likewise_cell *c)
+{
+ if (!c)
+ return;
+
+ if (c->conn)
+ ads_destroy(&c->conn);
+
+ talloc_destroy(c);
+}
+
+/**********************************************************************
+ Free all cell entries and reset the list head to NULL
+ *********************************************************************/
+
+ void cell_list_destroy(void)
+{
+ struct likewise_cell *p = _lw_cell_list;
+
+ while (p) {
+ struct likewise_cell *q = p->next;
+
+ cell_destroy(p);
+
+ p = q;
+ }
+
+ _lw_cell_list = NULL;
+
+ return;
+}
+
+/**********************************************************************
+ Add a new cell structure to the list
+ *********************************************************************/
+
+ struct likewise_cell* cell_new(void)
+{
+ struct likewise_cell *c;
+
+ /* Each cell struct is a TALLOC_CTX* */
+
+ c = TALLOC_ZERO_P(NULL, struct likewise_cell);
+ if (!c) {
+ DEBUG(0,("cell_new: memory allocation failure!\n"));
+ return NULL;
+ }
+
+ return c;
+}
+
+/**********************************************************************
+ Add a new cell structure to the list
+ *********************************************************************/
+
+ bool cell_list_add(struct likewise_cell * cell)
+{
+ if (!cell) {
+ return false;
+ }
+
+ /* Always add to the end */
+
+ DLIST_ADD_END(_lw_cell_list, cell, struct likewise_cell *);
+
+ return true;
+}
+
+/**********************************************************************
+ Add a new cell structure to the list
+ *********************************************************************/
+
+ bool cell_list_remove(struct likewise_cell * cell)
+{
+ if (!cell) {
+ return false;
+ }
+
+ /* Remove and drop the cell structure */
+
+ DLIST_REMOVE(_lw_cell_list, cell);
+ talloc_destroy(cell);
+
+ return true;
+}
+
+/**********************************************************************
+ Set the containing DNS domain for a cell
+ *********************************************************************/
+
+ void cell_set_dns_domain(struct likewise_cell *c, const char *dns_domain)
+{
+ c->dns_domain = talloc_strdup(c, dns_domain);
+}
+
+/**********************************************************************
+ Set ADS connection for a cell
+ *********************************************************************/
+
+ void cell_set_connection(struct likewise_cell *c, ADS_STRUCT *ads)
+{
+ c->conn = ads;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ void cell_set_flags(struct likewise_cell *c, uint32_t flags)
+{
+ c->flags |= flags;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ void cell_clear_flags(struct likewise_cell *c, uint32_t flags)
+{
+ c->flags &= ~flags;
+}
+
+/**********************************************************************
+ Set the Cell's DN
+ *********************************************************************/
+
+ void cell_set_dn(struct likewise_cell *c, const char *dn)
+{
+ if ( c->dn) {
+ talloc_free(c->dn);
+ c->dn = NULL;
+ }
+
+ c->dn = talloc_strdup(c, dn);
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ void cell_set_domain_sid(struct likewise_cell *c, DOM_SID *sid)
+{
+ sid_copy(&c->domain_sid, sid);
+}
+
+/*
+ * Query Routines
+ */
+
+/**********************************************************************
+ *********************************************************************/
+
+ const char* cell_search_base(struct likewise_cell *c)
+{
+ if (!c)
+ return NULL;
+
+ return talloc_asprintf(c, "cn=%s,%s", ADEX_CELL_RDN, c->dn);
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ bool cell_search_forest(struct likewise_cell *c)
+{
+ uint32_t test_flags = LWCELL_FLAG_SEARCH_FOREST;
+
+ return ((c->flags & test_flags) == test_flags);
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ uint32_t cell_flags(struct likewise_cell *c)
+{
+ if (!c)
+ return 0;
+
+ return c->flags;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ const char *cell_dns_domain(struct likewise_cell *c)
+{
+ if (!c)
+ return NULL;
+
+ return c->dns_domain;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+ ADS_STRUCT *cell_connection(struct likewise_cell *c)
+{
+ if (!c)
+ return NULL;
+
+ return c->conn;
+}
+
+/*
+ * Connection functions
+ */
+
+/********************************************************************
+ *******************************************************************/
+
+ NTSTATUS cell_connect(struct likewise_cell *c)
+{
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS ads_status;
+ fstring dc_name;
+ struct sockaddr_storage dcip;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ /* have to at least have the AD domain name */
+
+ if (!c->dns_domain) {
+ nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* clear out any old information */
+
+ if (c->conn) {
+ ads_destroy(&c->conn);
+ c->conn = NULL;
+ }
+
+ /* now setup the new connection */
+
+ ads = ads_init(c->dns_domain, NULL, NULL);
+ BAIL_ON_PTR_ERROR(ads, nt_status);
+
+ ads->auth.password =
+ secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+ ads->auth.realm = SMB_STRDUP(lp_realm());
+
+ /* Make the connection. We should already have an initial
+ TGT using the machine creds */
+
+ if (cell_flags(c) & LWCELL_FLAG_GC_CELL) {
+ ads_status = ads_connect_gc(ads);
+ } else {
+ /* Set up server affinity for normal cells and the client
+ site name cache */
+
+ if (!get_dc_name("", c->dns_domain, dc_name, &dcip)) {
+ nt_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ ads_status = ads_connect(ads);
+ }
+
+
+ c->conn = ads;
+
+ nt_status = ads_ntstatus(ads_status);
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ ads_destroy(&ads);
+ c->conn = NULL;
+ }
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+ NTSTATUS cell_connect_dn(struct likewise_cell **c, const char *dn)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct likewise_cell *new_cell = NULL;
+ char *dns_domain = NULL;
+
+ if (*c || !dn) {
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ if ((new_cell = cell_new()) == NULL) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Set the DNS domain, dn, etc ... and add it to the list */
+
+ dns_domain = cell_dn_to_dns(dn);
+ cell_set_dns_domain(new_cell, dns_domain);
+ SAFE_FREE(dns_domain);
+
+ cell_set_dn(new_cell, dn);
+
+ nt_status = cell_connect(new_cell);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ *c = new_cell;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1,("LWI: Failled to connect to cell \"%s\" (%s)\n",
+ dn ? dn : "NULL", nt_errstr(nt_status)));
+ talloc_destroy(new_cell);
+ }
+
+ return nt_status;
+}
+
+
+/********************************************************************
+ *******************************************************************/
+
+#define MAX_SEARCH_COUNT 2
+
+ ADS_STATUS cell_do_search(struct likewise_cell *c,
+ const char *search_base,
+ int scope,
+ const char *expr,
+ const char **attrs,
+ LDAPMessage ** msg)
+{
+ int search_count = 0;
+ ADS_STATUS status;
+ NTSTATUS nt_status;
+
+ /* check for a NULL connection */
+
+ if (!c->conn) {
+ nt_status = cell_connect(c);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ status = ADS_ERROR_NT(nt_status);
+ return status;
+ }
+ }
+
+ DEBUG(10, ("cell_do_search: Base = %s, Filter = %s, Scope = %d, GC = %s\n",
+ search_base, expr, scope,
+ c->conn->server.gc ? "yes" : "no"));
+
+ /* we try multiple times in case the ADS_STRUCT is bad
+ and we need to reconnect */
+
+ while (search_count < MAX_SEARCH_COUNT) {
+ *msg = NULL;
+ status = ads_do_search(c->conn, search_base,
+ scope, expr, attrs, msg);
+ if (ADS_ERR_OK(status)) {
+ return status;
+ }
+
+
+ DEBUG(5, ("cell_do_search: search[%d] failed (%s)\n",
+ search_count, ads_errstr(status)));
+
+ search_count++;
+
+ /* Houston, we have a problem */
+
+ if (status.error_type == ENUM_ADS_ERROR_LDAP) {
+ switch (status.err.rc) {
+ case LDAP_TIMELIMIT_EXCEEDED:
+ case LDAP_TIMEOUT:
+ case -1: /* we get this error if we cannot contact
+ the LDAP server */
+ nt_status = cell_connect(c);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ status = ADS_ERROR_NT(nt_status);
+ return status;
+ }
+ break;
+ default:
+ /* we're all done here */
+ return status;
+ }
+ }
+ }
+
+ DEBUG(5, ("cell_do_search: exceeded maximum search count!\n"));
+
+ return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+}
diff --git a/source3/winbindd/idmap_adex/provider_unified.c b/source3/winbindd/idmap_adex/provider_unified.c
new file mode 100644
index 0000000000..f18534797e
--- /dev/null
+++ b/source3/winbindd/idmap_adex/provider_unified.c
@@ -0,0 +1,1180 @@
+/*
+ * idmap_adex
+ *
+ * Provider for RFC2307 and SFU AD Forests
+ *
+ * Copyright (C) Gerald (Jerry) Carter 2006-2008
+ *
+ * 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 "idmap_adex.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/* Information needed by the LDAP search filters */
+
+enum filterType { SidFilter, IdFilter, AliasFilter };
+
+struct lwcell_filter
+{
+ enum filterType ftype;
+ bool use2307;
+ union {
+ DOM_SID sid;
+ struct {
+ uint32_t id;
+ enum id_type type;
+ } id;
+ fstring alias;
+ } filter;
+};
+
+/********************************************************************
+ *******************************************************************/
+
+static char* build_id_filter(uint32_t id,
+ enum id_type type,
+ uint32_t search_flags)
+{
+ char *filter = NULL;
+ char *oc_filter, *attr_filter;
+ NTSTATUS nt_status;
+ TALLOC_CTX *frame = talloc_stackframe();
+ bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
+ == LWCELL_FLAG_USE_RFC2307_ATTRS);
+ bool use_gc = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
+ == LWCELL_FLAG_SEARCH_FOREST);
+ const char *oc;
+
+ /* Construct search filter for objectclass and attributes */
+
+ switch (type) {
+ case ID_TYPE_UID:
+ oc = ADEX_OC_USER;
+ if (use2307) {
+ oc = ADEX_OC_POSIX_USER;
+ if (use_gc) {
+ oc = AD_USER;
+ }
+ }
+ oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
+ attr_filter = talloc_asprintf(frame, "%s=%u",
+ ADEX_ATTR_UIDNUM, id);
+ break;
+
+ case ID_TYPE_GID:
+ oc = ADEX_OC_GROUP;
+ if (use2307) {
+ oc = ADEX_OC_POSIX_GROUP;
+ if (use_gc) {
+ oc = AD_GROUP;
+ }
+ }
+ oc_filter = talloc_asprintf(frame, "objectclass=%s", oc);
+ attr_filter = talloc_asprintf(frame, "%s=%u",
+ ADEX_ATTR_GIDNUM, id);
+ break;
+ default:
+ return NULL;
+ }
+
+ BAIL_ON_PTR_ERROR(oc_filter, nt_status);
+ BAIL_ON_PTR_ERROR(attr_filter, nt_status);
+
+ /* Use "keywords=%s" for non-schema cells */
+
+ if (use2307) {
+ filter = talloc_asprintf(frame, "(&(%s)(%s))",
+ oc_filter, attr_filter);
+ } else {
+ filter = talloc_asprintf(frame, "(&(keywords=%s)(keywords=%s))",
+ oc_filter, attr_filter);
+ }
+
+ talloc_destroy(oc_filter);
+ talloc_destroy(attr_filter);
+
+done:
+ /* Don't destroy the stackframe CTX since we are returning
+ memory from it */
+
+ return filter;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static char* build_alias_filter(const char *alias, uint32_t search_flags)
+{
+ char *filter = NULL;
+ char *user_attr_filter, *group_attr_filter;
+ NTSTATUS nt_status;
+ TALLOC_CTX *frame = talloc_stackframe();
+ bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS)
+ == LWCELL_FLAG_USE_RFC2307_ATTRS);
+ bool search_forest = ((search_flags & LWCELL_FLAG_SEARCH_FOREST)
+ == LWCELL_FLAG_SEARCH_FOREST);
+
+ /* Construct search filter for objectclass and attributes */
+
+ user_attr_filter = talloc_asprintf(frame, "%s=%s",
+ ADEX_ATTR_UID, alias);
+ group_attr_filter = talloc_asprintf(frame, "%s=%s",
+ ADEX_ATTR_DISPLAYNAME, alias);
+ BAIL_ON_PTR_ERROR(user_attr_filter, nt_status);
+ BAIL_ON_PTR_ERROR(group_attr_filter, nt_status);
+
+ /* Use "keywords=%s" for non-schema cells */
+
+ if (use2307) {
+ filter = talloc_asprintf(frame,
+ "(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))",
+ user_attr_filter,
+ search_forest ? AD_USER : ADEX_OC_POSIX_USER,
+ group_attr_filter,
+ search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP);
+ } else {
+ filter = talloc_asprintf(frame,
+ "(|(keywords=%s)(keywords=%s))",
+ user_attr_filter,
+ group_attr_filter);
+ }
+
+ talloc_destroy(user_attr_filter);
+ talloc_destroy(group_attr_filter);
+
+done:
+ /* Don't destroy the stackframe CTX since we are returning
+ memory from it */
+
+ return filter;
+}
+
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS search_cell(struct likewise_cell *c,
+ LDAPMessage **msg,
+ const struct lwcell_filter *fdata)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX* frame = talloc_stackframe();
+ char *filter = NULL;
+ const char *base = NULL;
+ ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+ const char *attrs[] = { "*", NULL };
+ int count;
+ char *sid_str;
+
+ /* get the filter and other search parameters */
+
+ switch (fdata->ftype) {
+ case SidFilter:
+ sid_str = sid_string_talloc(frame, &fdata->filter.sid);
+ BAIL_ON_PTR_ERROR(sid_str, nt_status);
+
+ filter = talloc_asprintf(frame, "(keywords=backLink=%s)",
+ sid_str);
+ break;
+ case IdFilter:
+ filter = build_id_filter(fdata->filter.id.id,
+ fdata->filter.id.type,
+ cell_flags(c));
+ break;
+ case AliasFilter:
+ filter = build_alias_filter(fdata->filter.alias,
+ cell_flags(c));
+ break;
+ default:
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ break;
+ }
+ BAIL_ON_PTR_ERROR(filter, nt_status);
+
+ base = cell_search_base(c);
+ BAIL_ON_PTR_ERROR(base, nt_status);
+
+ ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE,
+ filter, attrs, msg);
+
+ nt_status = ads_ntstatus(ads_status);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* Now check that we got only one reply */
+
+ count = ads_count_replies(c->conn, *msg);
+ if (count < 1) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ if ( count > 1) {
+ nt_status = NT_STATUS_DUPLICATE_NAME;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+done:
+ PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4);
+
+ talloc_destroy(CONST_DISCARD(char*, base));
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS search_domain(struct likewise_cell **cell,
+ LDAPMessage **msg,
+ const char *dn,
+ const DOM_SID *sid)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX* frame = talloc_stackframe();
+ int count;
+
+ nt_status = dc_search_domains(cell, msg, dn, sid);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* Now check that we got only one reply */
+
+ count = ads_count_replies(cell_connection(*cell), *msg);
+ if (count < 1) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ if ( count > 1) {
+ nt_status = NT_STATUS_DUPLICATE_NAME;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+done:
+ PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4);
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+
+/********************************************************************
+ Check that a DN is within the forest scope.
+ *******************************************************************/
+
+static bool check_forest_scope(const char *dn)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *p = NULL;
+ char *q = NULL;
+ char *dns_domain = NULL;
+ struct winbindd_tdc_domain *domain;
+
+ /* If the DN does *not* contain "$LikewiseIdentityCell",
+ assume this is a schema mode forest and it is in the
+ forest scope by definition. */
+
+ if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) {
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+ /* If this is a non-schema forest, then make sure that the DN
+ is in the form "...,cn=$LikewiseIdentityCell,DC=..." */
+
+ if ((q = strchr_m(p, ',')) == NULL) {
+ nt_status = NT_STATUS_OBJECT_NAME_INVALID;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ q++;
+ if (StrnCaseCmp(q, "dc=", 3) != 0) {
+ nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+
+ dns_domain = cell_dn_to_dns(q);
+ BAIL_ON_PTR_ERROR(dns_domain, nt_status);
+
+ domain = wcache_tdc_fetch_domain(frame, dns_domain);
+ if (!domain) {
+ nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ talloc_destroy(frame);
+ SAFE_FREE(dns_domain);
+
+ return NT_STATUS_IS_OK(nt_status);
+}
+
+
+
+/********************************************************************
+ Check that only one result was returned within the forest cell
+ scope.
+ *******************************************************************/
+
+static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list,
+ LDAPMessage **msg_list,
+ int num_resp,
+ char **dn,
+ DOM_SID *user_sid)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ int i;
+ ADS_STRUCT *ads = NULL;
+ LDAPMessage *msg = NULL;
+ int count = 0;
+ char *entry_dn = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ if (!dn || !user_sid) {
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ *dn = NULL;
+
+ if (!ads_list || !msg_list || (num_resp == 0)) {
+ nt_status = NT_STATUS_NO_SUCH_FILE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Loop over all msgs */
+
+ for (i=0; i<num_resp; i++) {
+ LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]);
+
+ while (e) {
+ entry_dn = ads_get_dn(ads_list[i], e);
+ BAIL_ON_PTR_ERROR(entry_dn, nt_status);
+
+ if (check_forest_scope(entry_dn)) {
+ count++;
+
+ /* If we've already broken the condition, no
+ need to continue */
+
+ if (count > 1) {
+ nt_status = NT_STATUS_DUPLICATE_NAME;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ ads = ads_list[i];
+ msg = e;
+ *dn = SMB_STRDUP(entry_dn);
+ BAIL_ON_PTR_ERROR((*dn), nt_status);
+ }
+
+ e = ads_next_entry(ads_list[i], e);
+ SAFE_FREE(entry_dn);
+ }
+ }
+
+ if (!ads || !msg) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* If we made is through the loop, then grab the user_sid and
+ run home to base */
+
+ /*
+ Try and get the SID from either objectSid or keywords.
+ We cannot use pull_sid() here since we want to try
+ both methods and not only one or the other (and we
+ have no full likewise_cell struct.
+
+ Fail if both are unavailable
+ */
+
+ if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) {
+ char **keywords;
+ char *s;
+ size_t num_lines = 0;
+
+ keywords = ads_pull_strings(ads, frame, msg, "keywords",
+ &num_lines);
+ BAIL_ON_PTR_ERROR(keywords, nt_status);
+
+ s = find_attr_string(keywords, num_lines, "backLink");
+ if (!s) {
+ nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ if (!string_to_sid(user_sid, s)) {
+ nt_status = NT_STATUS_INVALID_SID;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ SAFE_FREE(*dn);
+ }
+
+ talloc_destroy(frame);
+ SAFE_FREE(entry_dn);
+
+ return nt_status;
+}
+
+/********************************************************************
+ Search all forests. Each forest can have it's own forest-cell
+ settings so we have to generate the filter for each search.
+ We don't use gc_search_all_forests() since we may have a different
+ schema model in each forest and need to construct the search
+ filter for each GC search.
+ *******************************************************************/
+
+static NTSTATUS search_forest(struct likewise_cell *forest_cell,
+ LDAPMessage **msg,
+ const struct lwcell_filter *fdata)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *filter = NULL;
+ char *dn = NULL;
+ struct gc_info *gc = NULL;
+ ADS_STRUCT **ads_list = NULL;
+ LDAPMessage **msg_list = NULL;
+ int num_resp = 0;
+ LDAPMessage *m;
+ DOM_SID user_sid;
+ struct likewise_cell *domain_cell = NULL;
+
+ if ((gc = gc_search_start()) == NULL) {
+ nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ while (gc) {
+ char *sid_binstr = NULL;
+ uint32_t flags = LWCELL_FLAG_SEARCH_FOREST;
+
+ m = NULL;
+
+ flags |= cell_flags(gc->forest_cell);
+
+ switch (fdata->ftype) {
+ case SidFilter:
+ sid_binstr = sid_binstring(&fdata->filter.sid);
+ BAIL_ON_PTR_ERROR(sid_binstr, nt_status);
+
+ filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr);
+ SAFE_FREE(sid_binstr);
+ break;
+ case IdFilter:
+ filter = build_id_filter(fdata->filter.id.id,
+ fdata->filter.id.type, flags);
+ break;
+ case AliasFilter:
+ filter = build_alias_filter(fdata->filter.alias, flags);
+ break;
+ }
+
+ /* First find the sparse object in GC */
+ nt_status = gc_search_forest(gc, &m, filter);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ gc = gc->next;
+ continue;
+ }
+
+ nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell),
+ m, &ads_list, &msg_list,
+ &num_resp);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ gc = gc->next;
+ }
+
+ /* Uniqueness check across forests */
+
+ nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp,
+ &dn, &user_sid);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = search_domain(&domain_cell, &m, dn, &user_sid);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* Save the connection and results in the return parameters */
+
+ forest_cell->gc_search_cell = domain_cell;
+ *msg = m;
+
+done:
+ PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4);
+
+ SAFE_FREE(dn);
+
+ free_result_array(ads_list, msg_list, num_resp);
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS search_cell_list(struct likewise_cell **c,
+ LDAPMessage **m,
+ const struct lwcell_filter *fdata)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct likewise_cell *cell = NULL;
+ LDAPMessage *msg = NULL;
+ struct likewise_cell *result_cell = NULL;
+
+ if ((cell = cell_list_head()) == NULL) {
+ nt_status = NT_STATUS_INVALID_SERVER_STATE;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ while (cell) {
+ /* Clear any previous GC search results */
+
+ cell->gc_search_cell = NULL;
+
+ if (cell_search_forest(cell)) {
+ nt_status = search_forest(cell, &msg, fdata);
+ } else {
+ nt_status = search_cell(cell, &msg, fdata);
+ }
+
+ /* Always point to the search result cell.
+ In forests this might be for another domain
+ which means the schema model may be different */
+
+ result_cell = cell->gc_search_cell ?
+ cell->gc_search_cell : cell;
+
+ /* Check if we are done */
+
+ if (NT_STATUS_IS_OK(nt_status)) {
+ break;
+ }
+
+ /* No luck. Free memory and hit the next cell.
+ Forest searches always set the gc_search_cell
+ so give preference to that connection if possible. */
+
+ ads_msgfree(cell_connection(result_cell), msg);
+ msg = NULL;
+
+ cell = cell->next;
+ }
+
+ /* This might be assigning NULL but that is ok as long as we
+ give back the proper error code */
+
+ *c = result_cell;
+ *m = msg;
+
+done:
+ PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3);
+
+ return nt_status;
+}
+
+/********************************************************************
+ Pull the SID from an object which is always stored in the keywords
+ attribute as "backLink=S-1-5-21-..."
+ *******************************************************************/
+
+static NTSTATUS pull_sid(struct likewise_cell *c,
+ LDAPMessage *msg,
+ DOM_SID *sid)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+
+ ads = cell_connection(c);
+
+ /*
+ We have two ways of getting the sid:
+ (a) from the objectSID in case of a GC search,
+ (b) from backLink in the case of a cell search.
+ Pull the keywords attributes and grab the backLink.
+ */
+
+ if (!ads_pull_sid(ads, msg, "objectSid", sid)) {
+ char **keywords;
+ char *s;
+ size_t num_lines = 0;
+
+ keywords = ads_pull_strings(ads, frame, msg,
+ "keywords", &num_lines);
+ BAIL_ON_PTR_ERROR(keywords, nt_status);
+
+ s = find_attr_string(keywords, num_lines, "backLink");
+ if (!s) {
+ nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ if (!string_to_sid(sid, s)) {
+ nt_status = NT_STATUS_INVALID_SID;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS get_object_type(struct likewise_cell *c,
+ LDAPMessage *msg,
+ enum id_type *type)
+{
+ TALLOC_CTX *ctx = talloc_stackframe();
+ char **oc_list = NULL;
+ NTSTATUS nt_status = NT_STATUS_OK;
+ size_t list_size = 0;
+ char *s = NULL;
+ ADS_STRUCT *ads = NULL;
+
+ ads = cell_connection(c);
+
+ /* Deal with RFC 2307 support first */
+
+ if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
+ oc_list = ads_pull_strings(ads, ctx, msg,
+ "objectClass", &list_size);
+ if (!oc_list) {
+ nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ /* Check for posix classes and AD classes */
+
+ if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER)
+ || is_object_class(oc_list, list_size, AD_USER)) {
+ *type = ID_TYPE_UID;
+ } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP)
+ || is_object_class(oc_list, list_size, AD_GROUP)) {
+ *type = ID_TYPE_GID;
+ } else {
+ *type = ID_TYPE_NOT_SPECIFIED;
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ }
+ } else {
+ /* Default to non-schema mode */
+
+ oc_list = ads_pull_strings(ads, ctx, msg,
+ "keywords", &list_size);
+ if (!oc_list) {
+ nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ s = find_attr_string(oc_list, list_size, "objectClass");
+ if (!s) {
+ nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ if (strequal(s, ADEX_OC_USER)) {
+ *type = ID_TYPE_UID;
+ } else if (strequal(s, ADEX_OC_GROUP)) {
+ *type = ID_TYPE_GID;
+ } else {
+ *type = ID_TYPE_NOT_SPECIFIED;
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ talloc_destroy(ctx);
+
+ return nt_status;
+}
+
+/********************************************************************
+ Pull an attribute uint32_t value
+ *******************************************************************/
+
+static NTSTATUS get_object_uint32(struct likewise_cell *c,
+ LDAPMessage *msg,
+ const char *attrib,
+ uint32_t *x)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ char **keywords = NULL;
+ size_t list_size = 0;
+ TALLOC_CTX *frame = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+
+ ads = cell_connection(c);
+
+ /* Deal with RFC2307 schema */
+
+ if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
+ if (!ads_pull_uint32(ads, msg, attrib, x)) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+ } else {
+ /* Non-schema mode */
+ char *s = NULL;
+ uint32_t num;
+
+ keywords = ads_pull_strings(ads, frame, msg, "keywords",
+ &list_size);
+ BAIL_ON_PTR_ERROR(keywords, nt_status);
+
+ s = find_attr_string(keywords, list_size, attrib);
+ if (!s) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ num = strtoll(s, NULL, 10);
+ if (errno == ERANGE) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+ *x = num;
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS get_object_id(struct likewise_cell *c,
+ LDAPMessage *msg,
+ enum id_type type,
+ uint32_t *id)
+{
+ NTSTATUS nt_status = NT_STATUS_OK;
+ const char *id_attr;
+
+ /* Figure out which attribute we need to pull */
+
+ switch (type) {
+ case ID_TYPE_UID:
+ id_attr = ADEX_ATTR_UIDNUM;
+ break;
+ case ID_TYPE_GID:
+ id_attr = ADEX_ATTR_GIDNUM;
+ break;
+ default:
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ break;
+ }
+
+ nt_status = get_object_uint32(c, msg, id_attr, id);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+done:
+ return nt_status;
+}
+
+/********************************************************************
+ Pull the uid/gid and type from an object. This differs depending on
+ the cell flags.
+ *******************************************************************/
+
+static NTSTATUS pull_id(struct likewise_cell *c,
+ LDAPMessage *msg,
+ uint32_t *id,
+ enum id_type *type)
+{
+ NTSTATUS nt_status;
+
+ nt_status = get_object_type(c, msg, type);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = get_object_id(c, msg, *type, id);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+done:
+ return nt_status;
+}
+
+/********************************************************************
+ Pull an attribute string value
+ *******************************************************************/
+
+static NTSTATUS get_object_string(struct likewise_cell *c,
+ LDAPMessage *msg,
+ TALLOC_CTX *ctx,
+ const char *attrib,
+ char **string)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ char **keywords = NULL;
+ size_t list_size = 0;
+ TALLOC_CTX *frame = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+
+ *string = NULL;
+
+ ads = cell_connection(c);
+
+ /* Deal with RFC2307 schema */
+
+ if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) {
+ *string = ads_pull_string(ads, ctx, msg, attrib);
+ } else {
+ /* Non-schema mode */
+
+ char *s = NULL;
+
+ keywords = ads_pull_strings(ads, frame, msg,
+ "keywords", &list_size);
+ if (!keywords) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+ s = find_attr_string(keywords, list_size, attrib);
+ if (s) {
+ *string = talloc_strdup(ctx, s);
+ }
+ }
+
+ if (!*string) {
+ nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/********************************************************************
+ Pull the struct passwd fields for a user
+ *******************************************************************/
+
+static NTSTATUS pull_nss_info(struct likewise_cell *c,
+ LDAPMessage *msg,
+ TALLOC_CTX *ctx,
+ char **homedir,
+ char **shell,
+ char **gecos,
+ gid_t *p_gid)
+{
+ NTSTATUS nt_status;
+
+ nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, homedir);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, shell);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, gecos);
+ /* Gecos is often not set so ignore failures */
+
+ nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+done:
+ return nt_status;
+}
+
+/********************************************************************
+ Pull the struct passwd fields for a user
+ *******************************************************************/
+
+static NTSTATUS pull_alias(struct likewise_cell *c,
+ LDAPMessage *msg,
+ TALLOC_CTX *ctx,
+ char **alias)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ enum id_type type;
+ const char *attr = NULL;
+
+ /* Figure out if this is a user or a group */
+
+ nt_status = get_object_type(c, msg, &type);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ switch (type) {
+ case ID_TYPE_UID:
+ attr = ADEX_ATTR_UID;
+ break;
+ case ID_TYPE_GID:
+ /* What is the group attr for RFC2307 Forests? */
+ attr = ADEX_ATTR_DISPLAYNAME;
+ break;
+ default:
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ break;
+ }
+
+ nt_status = get_object_string(c, msg, ctx, attr, alias);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+done:
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS _ccp_get_sid_from_id(DOM_SID * sid,
+ uint32_t id, enum id_type type)
+{
+ struct likewise_cell *cell = NULL;
+ LDAPMessage *msg = NULL;
+ NTSTATUS nt_status;
+ struct lwcell_filter filter;
+
+ filter.ftype = IdFilter;
+ filter.filter.id.id = id;
+ filter.filter.id.type = type;
+
+ nt_status = search_cell_list(&cell, &msg, &filter);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = pull_sid(cell, msg, sid);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+done:
+ ads_msgfree(cell->conn, msg);
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS _ccp_get_id_from_sid(uint32_t * id,
+ enum id_type *type,
+ const DOM_SID * sid)
+{
+ struct likewise_cell *cell = NULL;
+ LDAPMessage *msg = NULL;
+ NTSTATUS nt_status;
+ struct lwcell_filter filter;
+
+ filter.ftype = SidFilter;
+ sid_copy(&filter.filter.sid, sid);
+
+ nt_status = search_cell_list(&cell, &msg, &filter);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = pull_id(cell, msg, id, type);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ if (*id < min_id_value()) {
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+done:
+ ads_msgfree(cell->conn, msg);
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+static NTSTATUS _ccp_nss_get_info(const DOM_SID * sid,
+ TALLOC_CTX * ctx,
+ char **homedir,
+ char **shell,
+ char **gecos, gid_t * p_gid)
+{
+ struct likewise_cell *cell = NULL;
+ LDAPMessage *msg = NULL;
+ NTSTATUS nt_status;
+ struct lwcell_filter filter;
+ enum id_type type;
+
+ filter.ftype = SidFilter;
+ sid_copy(&filter.filter.sid, sid);
+
+ nt_status = search_cell_list(&cell, &msg, &filter);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = get_object_type(cell, msg, &type);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ if (type != ID_TYPE_UID) {
+ nt_status = NT_STATUS_NO_SUCH_USER;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos,
+ (uint32_t*) p_gid);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+done:
+ ads_msgfree(cell->conn, msg);
+
+ return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx,
+ const char *domain,
+ const char *name, char **alias)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID sid;
+ struct likewise_cell *cell = NULL;
+ LDAPMessage *msg = NULL;
+ struct lwcell_filter filter;
+ enum lsa_SidType sid_type;
+
+ /* Convert the name to a SID */
+
+ nt_status = gc_name_to_sid(domain, name, &sid, &sid_type);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* Find the user/group */
+
+ filter.ftype = SidFilter;
+ sid_copy(&filter.filter.sid, &sid);
+
+ nt_status = search_cell_list(&cell, &msg, &filter);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* Pull the alias and return */
+
+ nt_status = pull_alias(cell, msg, ctx, alias);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+done:
+ PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3);
+
+ talloc_destroy(frame);
+ ads_msgfree(cell_connection(cell), msg);
+
+ return nt_status;
+}
+
+/**********************************************************************
+ Map from an alias name to the canonical, qualified name.
+ Ensure that the alias is only pull from the closest in which
+ the user or gorup is enabled in
+ *********************************************************************/
+
+static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx,
+ const char *domain,
+ const char *alias, char **name)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID sid;
+ struct likewise_cell *cell_alias = NULL;
+ LDAPMessage *msg_alias = NULL;
+ struct likewise_cell *cell_sid = NULL;
+ LDAPMessage *msg_sid = NULL;
+ struct lwcell_filter filter;
+ char *canonical_name = NULL;
+ enum lsa_SidType type;
+
+ /* Find the user/group */
+
+ filter.ftype = AliasFilter;
+ fstrcpy(filter.filter.alias, alias);
+
+ nt_status = search_cell_list(&cell_alias, &msg_alias, &filter);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ nt_status = pull_sid(cell_alias, msg_alias, &sid);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ /* Now search again for the SID according to the cell list.
+ Verify that the cell of both search results is the same
+ so that we only match an alias from the closest cell
+ in which a user/group has been instantied. */
+
+ filter.ftype = SidFilter;
+ sid_copy(&filter.filter.sid, &sid);
+
+ nt_status = search_cell_list(&cell_sid, &msg_sid, &filter);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ if (cell_alias != cell_sid) {
+ nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+ }
+
+ /* Finally do the GC sid/name conversion */
+
+ nt_status = gc_sid_to_name(&sid, &canonical_name, &type);
+ BAIL_ON_NTSTATUS_ERROR(nt_status);
+
+ *name = talloc_strdup(mem_ctx, canonical_name);
+ BAIL_ON_PTR_ERROR((*name), nt_status);
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3);
+
+ ads_msgfree(cell_connection(cell_alias), msg_alias);
+ ads_msgfree(cell_connection(cell_sid), msg_sid);
+
+ SAFE_FREE(canonical_name);
+
+ talloc_destroy(frame);
+
+ return nt_status;
+}
+
+/********************************************************************
+ *******************************************************************/
+
+struct cell_provider_api ccp_unified = {
+ .get_sid_from_id = _ccp_get_sid_from_id,
+ .get_id_from_sid = _ccp_get_id_from_sid,
+ .get_nss_info = _ccp_nss_get_info,
+ .map_to_alias = _ccp_map_to_alias,
+ .map_from_alias = _ccp_map_from_alias
+};
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index 894e7866b3..1febddf110 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -1023,10 +1023,11 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
DEBUG(10,("ads: lookup_groupmem: got sid %s from "
"cache\n", sid_string_dbg(&sid)));
sid_copy(&(*sid_mem)[*num_names], &sid);
- (*names)[*num_names] = talloc_asprintf(*names, "%s%c%s",
- domain_name,
- *lp_winbind_separator(),
- name );
+ (*names)[*num_names] = fill_domain_username_talloc(
+ *names,
+ domain_name,
+ name,
+ true);
(*name_types)[*num_names] = name_type;
(*num_names)++;
@@ -1071,11 +1072,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
{
sid_copy(&(*sid_mem)[*num_names],
&sid_mem_nocache[i]);
- (*names)[*num_names] = talloc_asprintf( *names,
- "%s%c%s",
- domains_nocache[i],
- *lp_winbind_separator(),
- names_nocache[i] );
+ (*names)[*num_names] =
+ fill_domain_username_talloc(
+ *names,
+ domains_nocache[i],
+ names_nocache[i],
+ true);
(*name_types)[*num_names] = name_types_nocache[i];
(*num_names)++;
}
diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c
index 1481aed8e1..7500bcbe5b 100644
--- a/source3/winbindd/winbindd_async.c
+++ b/source3/winbindd/winbindd_async.c
@@ -366,7 +366,7 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, bool success,
/********************************************************************
The lookup name call first contacts a DC in its own domain
- and fallbacks to contact a DC in the forest in our domain doesn't
+ and fallbacks to contact a DC if the forest in our domain doesn't
know the name.
********************************************************************/
diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c
index 088f946877..f2b6fbefb5 100644
--- a/source3/winbindd/winbindd_group.c
+++ b/source3/winbindd/winbindd_group.c
@@ -35,7 +35,11 @@ static void add_member(const char *domain, const char *user,
{
fstring name;
- fill_domain_username(name, domain, user, True);
+ if (domain != NULL) {
+ fill_domain_username(name, domain, user, True);
+ } else {
+ fstrcpy(name, user);
+ }
safe_strcat(name, ",", sizeof(name)-1);
string_append(pp_members, name);
*p_num_members += 1;
@@ -136,7 +140,7 @@ static void add_expanded_sid(const DOM_SID *sid,
continue;
}
- add_member(domain->name, names[i], pp_members, p_num_members);
+ add_member(NULL, names[i], pp_members, p_num_members);
}
done:
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index d9104ca600..9ff3899661 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -127,7 +127,7 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
DATA_BLOB blob;
enum ndr_err_code ndr_err;
- ndr_err = ndr_push_struct_blob(&blob, mem_ctx, info3,
+ ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, info3,
(ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
DEBUG(0,("append_info3_as_ndr: failed to append\n"));
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 4774bc8106..3836c46e36 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -569,6 +569,10 @@ bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
void parse_add_domuser(void *buf, char *domuser, int *len);
bool canonicalize_username(fstring username_inout, fstring domain, fstring user);
void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume);
+char *fill_domain_username_talloc(TALLOC_CTX *ctx,
+ const char *domain,
+ const char *user,
+ bool can_assume);
const char *get_winbind_pipe_dir(void) ;
char *get_winbind_priv_pipe_dir(void) ;
int open_winbindd_socket(void);
diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c
index df80ad8029..9fbea8e45b 100644
--- a/source3/winbindd/winbindd_rpc.c
+++ b/source3/winbindd/winbindd_rpc.c
@@ -854,7 +854,10 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
}
for (r=0; r<tmp_names.count; r++) {
- (*names)[i+r] = CONST_DISCARD(char *, tmp_names.names[r].string);
+ (*names)[i+r] = fill_domain_username_talloc(mem_ctx,
+ domain->name,
+ tmp_names.names[r].string,
+ true);
(*name_types)[i+r] = tmp_types.ids[r];
}
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index e7b6576317..5b5ca41a74 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -1160,7 +1160,7 @@ void parse_add_domuser(void *buf, char *domuser, int *len)
}
}
- safe_strcpy(buf, user, *len);
+ safe_strcpy((char *)buf, user, *len);
}
/* Ensure an incoming username from NSS is fully qualified. Replace the
@@ -1213,6 +1213,33 @@ void fill_domain_username(fstring name, const char *domain, const char *user, bo
}
}
+/**
+ * talloc version of fill_domain_username()
+ * return NULL on talloc failure.
+ */
+char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
+ const char *domain,
+ const char *user,
+ bool can_assume)
+{
+ char *tmp_user, *name;
+
+ tmp_user = talloc_strdup(mem_ctx, user);
+ strlower_m(tmp_user);
+
+ if (can_assume && assume_domain(domain)) {
+ name = tmp_user;
+ } else {
+ name = talloc_asprintf(mem_ctx, "%s%c%s",
+ domain,
+ *lp_winbind_separator(),
+ tmp_user);
+ TALLOC_FREE(tmp_user);
+ }
+
+ return name;
+}
+
/*
* Winbindd socket accessor functions
*/