summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2008-10-08 02:21:49 +0200
committerJelmer Vernooij <jelmer@samba.org>2008-10-08 02:21:49 +0200
commit99b2089752e202adbf4113b1854636e1db2f97c7 (patch)
treed5f4be4c26a1f39fc91beeebb75044d2ced89d41
parent68837ff597bd39ff215ef30b4616692d2e31b1b4 (diff)
parent2024d87cf5ffa0633225ed189fa48f0f56151e7e (diff)
downloadsamba-99b2089752e202adbf4113b1854636e1db2f97c7.tar.gz
samba-99b2089752e202adbf4113b1854636e1db2f97c7.tar.bz2
samba-99b2089752e202adbf4113b1854636e1db2f97c7.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
-rw-r--r--lib/socket_wrapper/socket_wrapper.c38
-rw-r--r--source3/Makefile.in7
-rw-r--r--source3/auth/auth_netlogond.c321
-rw-r--r--source3/configure.in3
-rw-r--r--source3/dynconfig.c1
-rw-r--r--source3/include/dynconfig.h4
-rw-r--r--source3/include/proto.h5
-rw-r--r--source3/include/secrets.h2
-rw-r--r--source3/lib/errmap_unix.c136
-rw-r--r--source3/libnet/libnet_join.c11
-rw-r--r--source3/libsmb/clierror.c140
-rw-r--r--source3/m4/check_path.m419
-rw-r--r--source3/modules/vfs_acl_xattr.c58
-rw-r--r--source3/modules/vfs_smb_traffic_analyzer.c4
-rw-r--r--source3/passdb/secrets.c25
-rw-r--r--source3/winbindd/idmap_adex/domain_util.c8
-rw-r--r--source3/winbindd/idmap_adex/likewise_cell.c18
-rw-r--r--source3/winbindd/winbindd_dual.c4
-rw-r--r--source4/auth/gensec/gensec.c8
-rw-r--r--source4/auth/gensec/gensec.h2
-rw-r--r--source4/auth/gensec/spnego.c15
-rw-r--r--source4/dsdb/samdb/cracknames.c58
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c17
-rw-r--r--source4/dsdb/schema/schema_description.c27
-rw-r--r--source4/heimdal/kdc/krb5tgs.c34
-rw-r--r--source4/kdc/hdb-samba4.c15
-rw-r--r--source4/librpc/idl/drsblobs.idl10
-rw-r--r--source4/librpc/idl/drsuapi.idl2
-rw-r--r--source4/librpc/idl/misc.idl8
-rw-r--r--source4/rpc_server/dcesrv_auth.c4
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c68
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c52
-rw-r--r--source4/torture/rpc/drsuapi_cracknames.c1
-rw-r--r--source4/torture/rpc/lsa.c17
-rw-r--r--source4/utils/ad2oLschema.c14
-rwxr-xr-xtestprogs/blackbox/test_ldb.sh25
36 files changed, 906 insertions, 275 deletions
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c
index e8d27adc37..9d61976950 100644
--- a/lib/socket_wrapper/socket_wrapper.c
+++ b/lib/socket_wrapper/socket_wrapper.c
@@ -750,7 +750,7 @@ static struct swrap_packet *swrap_packet_init(struct timeval *tval,
int socket_type,
const unsigned char *payload,
size_t payload_len,
- unsigned long tcp_seq,
+ unsigned long tcp_seqno,
unsigned long tcp_ack,
unsigned char tcp_ctl,
int unreachable,
@@ -852,7 +852,7 @@ static struct swrap_packet *swrap_packet_init(struct timeval *tval,
case SOCK_STREAM:
packet->ip.p.tcp.source_port = src_port;
packet->ip.p.tcp.dest_port = dest_port;
- packet->ip.p.tcp.seq_num = htonl(tcp_seq);
+ packet->ip.p.tcp.seq_num = htonl(tcp_seqno);
packet->ip.p.tcp.ack_num = htonl(tcp_ack);
packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
packet->ip.p.tcp.control = tcp_ctl;
@@ -916,7 +916,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
{
const struct sockaddr_in *src_addr;
const struct sockaddr_in *dest_addr;
- unsigned long tcp_seq = 0;
+ unsigned long tcp_seqno = 0;
unsigned long tcp_ack = 0;
unsigned char tcp_ctl = 0;
int unreachable = 0;
@@ -937,7 +937,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
src_addr = (const struct sockaddr_in *)si->myname;
dest_addr = (const struct sockaddr_in *)addr;
- tcp_seq = si->io.pck_snd;
+ tcp_seqno = si->io.pck_snd;
tcp_ack = si->io.pck_rcv;
tcp_ctl = 0x02; /* SYN */
@@ -951,7 +951,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
dest_addr = (const struct sockaddr_in *)si->myname;
src_addr = (const struct sockaddr_in *)addr;
- tcp_seq = si->io.pck_rcv;
+ tcp_seqno = si->io.pck_rcv;
tcp_ack = si->io.pck_snd;
tcp_ctl = 0x12; /** SYN,ACK */
@@ -966,7 +966,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
src_addr = (const struct sockaddr_in *)addr;
/* Unreachable: resend the data of SWRAP_CONNECT_SEND */
- tcp_seq = si->io.pck_snd - 1;
+ tcp_seqno = si->io.pck_snd - 1;
tcp_ack = si->io.pck_rcv;
tcp_ctl = 0x02; /* SYN */
unreachable = 1;
@@ -979,7 +979,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
src_addr = (const struct sockaddr_in *)si->myname;
dest_addr = (const struct sockaddr_in *)addr;
- tcp_seq = si->io.pck_snd;
+ tcp_seqno = si->io.pck_snd;
tcp_ack = si->io.pck_rcv;
tcp_ctl = 0x10; /* ACK */
@@ -991,7 +991,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
dest_addr = (const struct sockaddr_in *)si->myname;
src_addr = (const struct sockaddr_in *)addr;
- tcp_seq = si->io.pck_rcv;
+ tcp_seqno = si->io.pck_rcv;
tcp_ack = si->io.pck_snd;
tcp_ctl = 0x02; /* SYN */
@@ -1005,7 +1005,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
src_addr = (const struct sockaddr_in *)si->myname;
dest_addr = (const struct sockaddr_in *)addr;
- tcp_seq = si->io.pck_snd;
+ tcp_seqno = si->io.pck_snd;
tcp_ack = si->io.pck_rcv;
tcp_ctl = 0x12; /* SYN,ACK */
@@ -1019,7 +1019,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
dest_addr = (const struct sockaddr_in *)si->myname;
src_addr = (const struct sockaddr_in *)addr;
- tcp_seq = si->io.pck_rcv;
+ tcp_seqno = si->io.pck_rcv;
tcp_ack = si->io.pck_snd;
tcp_ctl = 0x10; /* ACK */
@@ -1029,7 +1029,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
src_addr = (const struct sockaddr_in *)si->myname;
dest_addr = (const struct sockaddr_in *)si->peername;
- tcp_seq = si->io.pck_snd;
+ tcp_seqno = si->io.pck_snd;
tcp_ack = si->io.pck_rcv;
tcp_ctl = 0x18; /* PSH,ACK */
@@ -1047,7 +1047,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
buf, len, packet_len);
}
- tcp_seq = si->io.pck_rcv;
+ tcp_seqno = si->io.pck_rcv;
tcp_ack = si->io.pck_snd;
tcp_ctl = 0x14; /** RST,ACK */
@@ -1061,7 +1061,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
return NULL;
}
- tcp_seq = si->io.pck_rcv;
+ tcp_seqno = si->io.pck_rcv;
tcp_ack = si->io.pck_snd;
tcp_ctl = 0x14; /* RST,ACK */
@@ -1071,7 +1071,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
dest_addr = (const struct sockaddr_in *)si->myname;
src_addr = (const struct sockaddr_in *)si->peername;
- tcp_seq = si->io.pck_rcv;
+ tcp_seqno = si->io.pck_rcv;
tcp_ack = si->io.pck_snd;
tcp_ctl = 0x18; /* PSH,ACK */
@@ -1087,7 +1087,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
return NULL;
}
- tcp_seq = si->io.pck_rcv;
+ tcp_seqno = si->io.pck_rcv;
tcp_ack = si->io.pck_snd;
tcp_ctl = 0x14; /* RST,ACK */
@@ -1123,7 +1123,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
src_addr = (const struct sockaddr_in *)si->myname;
dest_addr = (const struct sockaddr_in *)si->peername;
- tcp_seq = si->io.pck_snd;
+ tcp_seqno = si->io.pck_snd;
tcp_ack = si->io.pck_rcv;
tcp_ctl = 0x11; /* FIN, ACK */
@@ -1137,7 +1137,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
dest_addr = (const struct sockaddr_in *)si->myname;
src_addr = (const struct sockaddr_in *)si->peername;
- tcp_seq = si->io.pck_rcv;
+ tcp_seqno = si->io.pck_rcv;
tcp_ack = si->io.pck_snd;
tcp_ctl = 0x11; /* FIN,ACK */
@@ -1151,7 +1151,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
src_addr = (const struct sockaddr_in *)si->myname;
dest_addr = (const struct sockaddr_in *)si->peername;
- tcp_seq = si->io.pck_snd;
+ tcp_seqno = si->io.pck_snd;
tcp_ack = si->io.pck_rcv;
tcp_ctl = 0x10; /* ACK */
@@ -1164,7 +1164,7 @@ static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
(const unsigned char *)buf, len,
- tcp_seq, tcp_ack, tcp_ctl, unreachable,
+ tcp_seqno, tcp_ack, tcp_ctl, unreachable,
packet_len);
}
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 61e946e7cd..eb6a05cba5 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -127,6 +127,7 @@ LOGFILEBASE = @logfilebase@
CONFIGFILE = $(CONFIGDIR)/smb.conf
LMHOSTSFILE = $(CONFIGDIR)/lmhosts
CTDBDIR = @ctdbdir@
+NCALRPCDIR = @ncalrpcdir@
# This is where smbpasswd et al go
PRIVATEDIR = @privatedir@
@@ -166,6 +167,7 @@ PATH_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" \
-DLOGFILEBASE=\"$(LOGFILEBASE)\" \
-DSHLIBEXT=\"@SHLIBEXT@\" \
-DCTDBDIR=\"$(CTDBDIR)\" \
+ -DNCALRPCDIR=\"$(NCALRPCDIR)\" \
-DCONFIGDIR=\"$(CONFIGDIR)\" \
-DCODEPAGEDIR=\"$(CODEPAGEDIR)\" \
-DCACHEDIR=\"$(CACHEDIR)\" \
@@ -636,6 +638,7 @@ AUTH_SERVER_OBJ = auth/auth_server.o
AUTH_UNIX_OBJ = auth/auth_unix.o
AUTH_WINBIND_OBJ = auth/auth_winbind.o
AUTH_SCRIPT_OBJ = auth/auth_script.o
+AUTH_NETLOGOND_OBJ = auth/auth_netlogond.o
AUTH_OBJ = auth/auth.o @AUTH_STATIC@ auth/auth_util.o auth/token_util.o \
auth/auth_compat.o auth/auth_ntlmssp.o \
@@ -2195,6 +2198,10 @@ bin/script.@SHLIBEXT@: $(BINARY_PREREQS) $(AUTH_SCRIPT_OBJ)
@echo "Building plugin $@"
@$(SHLD_MODULE) $(AUTH_SCRIPT_OBJ)
+bin/netlogond.@SHLIBEXT@: $(BINARY_PREREQS) $(AUTH_NETLOGOND_OBJ)
+ @echo "Building plugin $@"
+ @$(SHLD_MODULE) $(AUTH_NETLOGOND_OBJ)
+
bin/smbserver.@SHLIBEXT@: $(BINARY_PREREQS) $(AUTH_SERVER_OBJ)
@echo "Building plugin $@"
@$(SHLD_MODULE) $(AUTH_SERVER_OBJ)
diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c
new file mode 100644
index 0000000000..a57f3b74a3
--- /dev/null
+++ b/source3/auth/auth_netlogond.c
@@ -0,0 +1,321 @@
+/*
+ Unix SMB/CIFS implementation.
+ Authenticate against a netlogon pipe listening on a unix domain socket
+ Copyright (C) Volker Lendecke 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 "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
+
+static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx,
+ const struct auth_context *auth_context,
+ const char *ncalrpc_sockname,
+ uint8_t schannel_key[16],
+ const auth_usersupplied_info *user_info,
+ struct netr_SamInfo3 **pinfo3,
+ NTSTATUS *schannel_bind_result)
+{
+ struct rpc_pipe_client *p;
+ struct cli_pipe_auth_data *auth;
+ struct netr_SamInfo3 *info3 = NULL;
+ NTSTATUS status;
+
+ *schannel_bind_result = NT_STATUS_OK;
+
+ status = rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpc_sockname,
+ &ndr_table_netlogon.syntax_id, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+
+ status = rpccli_schannel_bind_data(p, lp_workgroup(),
+ PIPE_AUTH_LEVEL_PRIVACY,
+ schannel_key, &auth);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("rpccli_schannel_bind_data failed: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(p);
+ return status;
+ }
+
+ status = rpc_pipe_bind(p, auth);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
+ TALLOC_FREE(p);
+ *schannel_bind_result = status;
+ return status;
+ }
+
+ /*
+ * We have to fake a struct dcinfo, so that
+ * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys.
+ */
+
+ p->dc = talloc(p, struct dcinfo);
+ if (p->dc == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(p);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ memcpy(p->dc->sess_key, schannel_key, 16);
+
+ status = rpccli_netlogon_sam_network_logon_ex(
+ p, p,
+ user_info->logon_parameters,/* flags such as 'allow
+ * workstation logon' */
+ global_myname(), /* server name */
+ user_info->smb_name, /* user name logging on. */
+ user_info->client_domain, /* domain name */
+ user_info->wksta_name, /* workstation name */
+ (uchar *)auth_context->challenge.data, /* 8 byte challenge. */
+ user_info->lm_resp, /* lanman 24 byte response */
+ user_info->nt_resp, /* nt 24 byte response */
+ &info3); /* info3 out */
+
+ DEBUG(10, ("rpccli_netlogon_sam_network_logon_ex returned %s\n",
+ nt_errstr(status)));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(p);
+ return status;
+ }
+
+ *pinfo3 = talloc_move(mem_ctx, &info3);
+
+ TALLOC_FREE(p);
+ return NT_STATUS_OK;
+}
+
+static char *mymachinepw(TALLOC_CTX *mem_ctx)
+{
+ fstring pwd;
+ const char *script;
+ char *to_free = NULL;
+ ssize_t nread;
+ int ret, fd;
+
+ script = lp_parm_const_string(
+ GLOBAL_SECTION_SNUM, "auth_netlogond", "machinepwscript",
+ NULL);
+
+ if (script == NULL) {
+ to_free = talloc_asprintf(talloc_tos(), "%s/%s",
+ get_dyn_SBINDIR(), "mymachinepw");
+ script = to_free;
+ }
+ if (script == NULL) {
+ return NULL;
+ }
+
+ ret = smbrun(script, &fd);
+ DEBUG(ret ? 0 : 3, ("mymachinepw: Running the command `%s' gave %d\n",
+ script, ret));
+ TALLOC_FREE(to_free);
+
+ if (ret != 0) {
+ return NULL;
+ }
+
+ pwd[sizeof(pwd)-1] = '\0';
+
+ nread = read(fd, pwd, sizeof(pwd)-1);
+ close(fd);
+
+ if (nread <= 0) {
+ DEBUG(3, ("mymachinepwd: Could not read password\n"));
+ return NULL;
+ }
+
+ DEBUG(0, ("pwd: %d [%s]\n", (int)nread, pwd));
+
+ if (pwd[nread-1] == '\n') {
+ pwd[nread-1] = '\0';
+ }
+
+ return talloc_strdup(mem_ctx, pwd);
+}
+
+static NTSTATUS check_netlogond_security(const struct auth_context *auth_context,
+ void *my_private_data,
+ TALLOC_CTX *mem_ctx,
+ const auth_usersupplied_info *user_info,
+ auth_serversupplied_info **server_info)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct netr_SamInfo3 *info3 = NULL;
+ struct rpc_pipe_client *p;
+ struct cli_pipe_auth_data *auth;
+ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+ char *plaintext_machinepw;
+ uint8_t machine_password[16];
+ uint8_t schannel_key[16];
+ NTSTATUS schannel_bind_result, status;
+ struct named_mutex *mutex;
+ const char *ncalrpcsock;
+
+ ncalrpcsock = lp_parm_const_string(
+ GLOBAL_SECTION_SNUM, "auth_netlogond", "socket", NULL);
+
+ if (ncalrpcsock == NULL) {
+ ncalrpcsock = talloc_asprintf(talloc_tos(), "%s/%s",
+ get_dyn_NCALRPCDIR(), "DEFAULT");
+ }
+
+ if (ncalrpcsock == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if (!secrets_fetch_local_schannel_key(schannel_key)) {
+ goto new_key;
+ }
+
+ status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock,
+ schannel_key, user_info, &info3,
+ &schannel_bind_result);
+
+ DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status)));
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto okay;
+ }
+
+ if (NT_STATUS_IS_OK(schannel_bind_result)) {
+ /*
+ * This is a real failure from the DC
+ */
+ goto done;
+ }
+
+ new_key:
+
+ mutex = grab_named_mutex(talloc_tos(), "LOCAL_SCHANNEL_KEY", 60);
+ if (mutex == NULL) {
+ DEBUG(10, ("Could not get mutex LOCAL_SCHANNEL_KEY\n"));
+ status = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
+
+ DEBUG(10, ("schannel bind failed, setting up new key\n"));
+
+ status = rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpcsock,
+ &ndr_table_netlogon.syntax_id, &p);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ status = rpccli_anon_bind_data(p, &auth);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("rpccli_anon_bind_data failed: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ status = rpc_pipe_bind(p, auth);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
+ goto done;
+ }
+
+ TALLOC_FREE(auth);
+
+ plaintext_machinepw = mymachinepw(talloc_tos());
+ if (plaintext_machinepw == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ E_md4hash(plaintext_machinepw, machine_password);
+
+ TALLOC_FREE(plaintext_machinepw);
+
+ status = rpccli_netlogon_setup_creds(
+ p, global_myname(), lp_workgroup(), global_myname(),
+ global_myname(), machine_password, SEC_CHAN_BDC, &neg_flags);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("rpccli_netlogon_setup_creds failed: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ memcpy(schannel_key, p->dc->sess_key, 16);
+ secrets_store_local_schannel_key(schannel_key);
+
+ TALLOC_FREE(p);
+
+ /*
+ * Retry the authentication with the mutex held. This way nobody else
+ * can step on our toes.
+ */
+
+ status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock,
+ schannel_key, user_info, &info3,
+ &schannel_bind_result);
+
+ DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status)));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ okay:
+
+ status = make_server_info_info3(mem_ctx, user_info->smb_name,
+ user_info->domain, server_info,
+ info3);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("make_server_info_info3 failed: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ status = NT_STATUS_OK;
+
+ done:
+ TALLOC_FREE(frame);
+ return status;
+}
+
+/* module initialisation */
+static NTSTATUS auth_init_netlogond(struct auth_context *auth_context,
+ const char *param,
+ auth_methods **auth_method)
+{
+ if (!make_auth_methods(auth_context, auth_method)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*auth_method)->name = "netlogond";
+ (*auth_method)->auth = check_netlogond_security;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS auth_netlogond_init(void)
+{
+ smb_register_auth(AUTH_INTERFACE_VERSION, "netlogond",
+ auth_init_netlogond);
+ return NT_STATUS_OK;
+}
diff --git a/source3/configure.in b/source3/configure.in
index 545a5653de..1eba4a0a58 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -404,7 +404,7 @@ AC_SUBST(DYNEXP)
dnl Add modules that have to be built by default here
dnl These have to be built static:
-default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl2 rpc_ntsvcs2 rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog2 auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin vfs_default nss_info_template"
+default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl2 rpc_ntsvcs2 rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog2 auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin auth_netlogond vfs_default nss_info_template"
dnl These are preferably build shared, and static if dlopen() is not available
default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_acl_xattr vfs_smb_traffic_analyzer"
@@ -6077,6 +6077,7 @@ SMB_MODULE(auth_server, \$(AUTH_SERVER_OBJ), "bin/smbserver.$SHLIBEXT", AUTH)
SMB_MODULE(auth_domain, \$(AUTH_DOMAIN_OBJ), "bin/domain.$SHLIBEXT", AUTH)
SMB_MODULE(auth_builtin, \$(AUTH_BUILTIN_OBJ), "bin/builtin.$SHLIBEXT", AUTH)
SMB_MODULE(auth_script, \$(AUTH_SCRIPT_OBJ), "bin/script.$SHLIBEXT", AUTH)
+SMB_MODULE(auth_netlogond, \$(AUTH_NETLOGOND_OBJ), "bin/netlogond.$SHLIBEXT", AUTH)
SMB_SUBSYSTEM(AUTH,auth/auth.o)
SMB_MODULE(vfs_default, \$(VFS_DEFAULT_OBJ), "bin/default.$SHLIBEXT", VFS)
diff --git a/source3/dynconfig.c b/source3/dynconfig.c
index 3a54507599..6125f9944c 100644
--- a/source3/dynconfig.c
+++ b/source3/dynconfig.c
@@ -77,6 +77,7 @@ DEFINE_DYN_CONFIG_PARAM(MODULESDIR)
DEFINE_DYN_CONFIG_PARAM(SHLIBEXT)
DEFINE_DYN_CONFIG_PARAM(LOCKDIR)
DEFINE_DYN_CONFIG_PARAM(PIDDIR)
+DEFINE_DYN_CONFIG_PARAM(NCALRPCDIR)
DEFINE_DYN_CONFIG_PARAM(SMB_PASSWD_FILE)
DEFINE_DYN_CONFIG_PARAM(PRIVATE_DIR)
diff --git a/source3/include/dynconfig.h b/source3/include/dynconfig.h
index 758bde33cc..8267064f23 100644
--- a/source3/include/dynconfig.h
+++ b/source3/include/dynconfig.h
@@ -71,6 +71,10 @@ const char *get_dyn_PIDDIR(void);
const char *set_dyn_PIDDIR(const char *newpath);
bool is_default_dyn_PIDDIR(void);
+const char *get_dyn_NCALRPCDIR(void);
+const char *set_dyn_NCALRPCDIR(const char *newpath);
+bool is_default_dyn_NCALRPCDIR(void);
+
const char *get_dyn_SMB_PASSWD_FILE(void);
const char *set_dyn_SMB_PASSWD_FILE(const char *newpath);
bool is_default_dyn_SMB_PASSWD_FILE(void);
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 7cdcba19ab..d7acdcb910 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -46,6 +46,8 @@ bool password_ok(const char *smb_name, DATA_BLOB password_blob);
void attempt_machine_password_change(void);
NTSTATUS auth_domain_init(void);
+NTSTATUS auth_netlogond_init(void);
+
/* The following definitions come from auth/auth_ntlmssp.c */
NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state);
@@ -513,6 +515,7 @@ void display_set_stderr(void);
/* The following definitions come from lib/errmap_unix.c */
NTSTATUS map_nt_error_from_unix(int unix_error);
+int map_errno_from_nt_status(NTSTATUS status);
/* The following definitions come from lib/events.c */
@@ -6421,6 +6424,8 @@ bool secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
struct dcinfo **ppdc);
bool secrets_store_generic(const char *owner, const char *key, const char *secret);
char *secrets_fetch_generic(const char *owner, const char *key);
+bool secrets_store_local_schannel_key(uint8_t schannel_key[16]);
+bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16]);
/* The following definitions come from passdb/util_builtin.c */
diff --git a/source3/include/secrets.h b/source3/include/secrets.h
index d9f457558b..3c8e2ccf81 100644
--- a/source3/include/secrets.h
+++ b/source3/include/secrets.h
@@ -45,6 +45,8 @@
#define SECRETS_LDAP_BIND_PW "SECRETS/LDAP_BIND_PW"
+#define SECRETS_LOCAL_SCHANNEL_KEY "SECRETS/LOCAL_SCHANNEL_KEY"
+
/* Authenticated user info is stored in secrets.tdb under these keys */
#define SECRETS_AUTH_USER "SECRETS/AUTH_USER"
diff --git a/source3/lib/errmap_unix.c b/source3/lib/errmap_unix.c
index 2cd2386c5c..9adb237096 100644
--- a/source3/lib/errmap_unix.c
+++ b/source3/lib/errmap_unix.c
@@ -128,3 +128,139 @@ NTSTATUS map_nt_error_from_unix(int unix_error)
/* Default return */
return NT_STATUS_ACCESS_DENIED;
}
+
+/* Return a UNIX errno from a NT status code */
+static const struct {
+ NTSTATUS status;
+ int error;
+} nt_errno_map[] = {
+ {NT_STATUS_ACCESS_VIOLATION, EACCES},
+ {NT_STATUS_INVALID_HANDLE, EBADF},
+ {NT_STATUS_ACCESS_DENIED, EACCES},
+ {NT_STATUS_OBJECT_NAME_NOT_FOUND, ENOENT},
+ {NT_STATUS_OBJECT_PATH_NOT_FOUND, ENOENT},
+ {NT_STATUS_SHARING_VIOLATION, EBUSY},
+ {NT_STATUS_OBJECT_PATH_INVALID, ENOTDIR},
+ {NT_STATUS_OBJECT_NAME_COLLISION, EEXIST},
+ {NT_STATUS_PATH_NOT_COVERED, ENOENT},
+ {NT_STATUS_UNSUCCESSFUL, EINVAL},
+ {NT_STATUS_NOT_IMPLEMENTED, ENOSYS},
+ {NT_STATUS_IN_PAGE_ERROR, EFAULT},
+ {NT_STATUS_BAD_NETWORK_NAME, ENOENT},
+#ifdef EDQUOT
+ {NT_STATUS_PAGEFILE_QUOTA, EDQUOT},
+ {NT_STATUS_QUOTA_EXCEEDED, EDQUOT},
+ {NT_STATUS_REGISTRY_QUOTA_LIMIT, EDQUOT},
+ {NT_STATUS_LICENSE_QUOTA_EXCEEDED, EDQUOT},
+#endif
+#ifdef ETIME
+ {NT_STATUS_TIMER_NOT_CANCELED, ETIME},
+#endif
+ {NT_STATUS_INVALID_PARAMETER, EINVAL},
+ {NT_STATUS_NO_SUCH_DEVICE, ENODEV},
+ {NT_STATUS_NO_SUCH_FILE, ENOENT},
+#ifdef ENODATA
+ {NT_STATUS_END_OF_FILE, ENODATA},
+#endif
+#ifdef ENOMEDIUM
+ {NT_STATUS_NO_MEDIA_IN_DEVICE, ENOMEDIUM},
+ {NT_STATUS_NO_MEDIA, ENOMEDIUM},
+#endif
+ {NT_STATUS_NONEXISTENT_SECTOR, ESPIPE},
+ {NT_STATUS_NO_MEMORY, ENOMEM},
+ {NT_STATUS_CONFLICTING_ADDRESSES, EADDRINUSE},
+ {NT_STATUS_NOT_MAPPED_VIEW, EINVAL},
+ {NT_STATUS_UNABLE_TO_FREE_VM, EADDRINUSE},
+ {NT_STATUS_ACCESS_DENIED, EACCES},
+ {NT_STATUS_BUFFER_TOO_SMALL, ENOBUFS},
+ {NT_STATUS_WRONG_PASSWORD, EACCES},
+ {NT_STATUS_LOGON_FAILURE, EACCES},
+ {NT_STATUS_INVALID_WORKSTATION, EACCES},
+ {NT_STATUS_INVALID_LOGON_HOURS, EACCES},
+ {NT_STATUS_PASSWORD_EXPIRED, EACCES},
+ {NT_STATUS_ACCOUNT_DISABLED, EACCES},
+ {NT_STATUS_DISK_FULL, ENOSPC},
+ {NT_STATUS_INVALID_PIPE_STATE, EPIPE},
+ {NT_STATUS_PIPE_BUSY, EPIPE},
+ {NT_STATUS_PIPE_DISCONNECTED, EPIPE},
+ {NT_STATUS_PIPE_NOT_AVAILABLE, ENOSYS},
+ {NT_STATUS_FILE_IS_A_DIRECTORY, EISDIR},
+ {NT_STATUS_NOT_SUPPORTED, ENOSYS},
+ {NT_STATUS_NOT_A_DIRECTORY, ENOTDIR},
+ {NT_STATUS_DIRECTORY_NOT_EMPTY, ENOTEMPTY},
+ {NT_STATUS_NETWORK_UNREACHABLE, ENETUNREACH},
+ {NT_STATUS_HOST_UNREACHABLE, EHOSTUNREACH},
+ {NT_STATUS_CONNECTION_ABORTED, ECONNABORTED},
+ {NT_STATUS_CONNECTION_REFUSED, ECONNREFUSED},
+ {NT_STATUS_TOO_MANY_LINKS, EMLINK},
+ {NT_STATUS_NETWORK_BUSY, EBUSY},
+ {NT_STATUS_DEVICE_DOES_NOT_EXIST, ENODEV},
+#ifdef ELIBACC
+ {NT_STATUS_DLL_NOT_FOUND, ELIBACC},
+#endif
+ {NT_STATUS_PIPE_BROKEN, EPIPE},
+ {NT_STATUS_REMOTE_NOT_LISTENING, ECONNREFUSED},
+ {NT_STATUS_NETWORK_ACCESS_DENIED, EACCES},
+ {NT_STATUS_TOO_MANY_OPENED_FILES, EMFILE},
+#ifdef EPROTO
+ {NT_STATUS_DEVICE_PROTOCOL_ERROR, EPROTO},
+#endif
+ {NT_STATUS_FLOAT_OVERFLOW, ERANGE},
+ {NT_STATUS_FLOAT_UNDERFLOW, ERANGE},
+ {NT_STATUS_INTEGER_OVERFLOW, ERANGE},
+ {NT_STATUS_MEDIA_WRITE_PROTECTED, EROFS},
+ {NT_STATUS_PIPE_CONNECTED, EISCONN},
+ {NT_STATUS_MEMORY_NOT_ALLOCATED, EFAULT},
+ {NT_STATUS_FLOAT_INEXACT_RESULT, ERANGE},
+ {NT_STATUS_ILL_FORMED_PASSWORD, EACCES},
+ {NT_STATUS_PASSWORD_RESTRICTION, EACCES},
+ {NT_STATUS_ACCOUNT_RESTRICTION, EACCES},
+ {NT_STATUS_PORT_CONNECTION_REFUSED, ECONNREFUSED},
+ {NT_STATUS_NAME_TOO_LONG, ENAMETOOLONG},
+ {NT_STATUS_REMOTE_DISCONNECT, ESHUTDOWN},
+ {NT_STATUS_CONNECTION_DISCONNECTED, ECONNABORTED},
+ {NT_STATUS_CONNECTION_RESET, ENETRESET},
+#ifdef ENOTUNIQ
+ {NT_STATUS_IP_ADDRESS_CONFLICT1, ENOTUNIQ},
+ {NT_STATUS_IP_ADDRESS_CONFLICT2, ENOTUNIQ},
+#endif
+ {NT_STATUS_PORT_MESSAGE_TOO_LONG, EMSGSIZE},
+ {NT_STATUS_PROTOCOL_UNREACHABLE, ENOPROTOOPT},
+ {NT_STATUS_ADDRESS_ALREADY_EXISTS, EADDRINUSE},
+ {NT_STATUS_PORT_UNREACHABLE, EHOSTUNREACH},
+ {NT_STATUS_IO_TIMEOUT, ETIMEDOUT},
+ {NT_STATUS_RETRY, EAGAIN},
+#ifdef ENOTUNIQ
+ {NT_STATUS_DUPLICATE_NAME, ENOTUNIQ},
+#endif
+#ifdef ECOMM
+ {NT_STATUS_NET_WRITE_FAULT, ECOMM},
+#endif
+#ifdef EXDEV
+ {NT_STATUS_NOT_SAME_DEVICE, EXDEV},
+#endif
+ {NT_STATUS(0), 0}
+};
+
+int map_errno_from_nt_status(NTSTATUS status)
+{
+ int i;
+ DEBUG(10,("map_errno_from_nt_status: 32 bit codes: code=%08x\n",
+ NT_STATUS_V(status)));
+
+ /* Status codes without this bit set are not errors */
+
+ if (!(NT_STATUS_V(status) & 0xc0000000)) {
+ return 0;
+ }
+
+ for (i=0;nt_errno_map[i].error;i++) {
+ if (NT_STATUS_V(nt_errno_map[i].status) ==
+ NT_STATUS_V(status)) {
+ return nt_errno_map[i].error;
+ }
+ }
+
+ /* for all other cases - a default code */
+ return EINVAL;
+}
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index a39dee676f..ab8af0be6b 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -357,10 +357,15 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
strupper_m(spn);
spn_array[0] = spn;
- if (name_to_fqdn(my_fqdn, r->in.machine_name) &&
- !strequal(my_fqdn, r->in.machine_name)) {
+ if (!name_to_fqdn(my_fqdn, r->in.machine_name)
+ || (strchr(my_fqdn, '.') == NULL)) {
+ fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name,
+ r->out.dns_domain_name);
+ }
+
+ strlower_m(my_fqdn);
- strlower_m(my_fqdn);
+ if (!strequal(my_fqdn, r->in.machine_name)) {
spn = talloc_asprintf(mem_ctx, "HOST/%s", my_fqdn);
if (!spn) {
return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
diff --git a/source3/libsmb/clierror.c b/source3/libsmb/clierror.c
index 36746419f7..54f8a7a43c 100644
--- a/source3/libsmb/clierror.c
+++ b/source3/libsmb/clierror.c
@@ -236,142 +236,6 @@ void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *ecode)
*ecode = SVAL(cli->inbuf,smb_err);
}
-/* Return a UNIX errno from a NT status code */
-static const struct {
- NTSTATUS status;
- int error;
-} nt_errno_map[] = {
- {NT_STATUS_ACCESS_VIOLATION, EACCES},
- {NT_STATUS_INVALID_HANDLE, EBADF},
- {NT_STATUS_ACCESS_DENIED, EACCES},
- {NT_STATUS_OBJECT_NAME_NOT_FOUND, ENOENT},
- {NT_STATUS_OBJECT_PATH_NOT_FOUND, ENOENT},
- {NT_STATUS_SHARING_VIOLATION, EBUSY},
- {NT_STATUS_OBJECT_PATH_INVALID, ENOTDIR},
- {NT_STATUS_OBJECT_NAME_COLLISION, EEXIST},
- {NT_STATUS_PATH_NOT_COVERED, ENOENT},
- {NT_STATUS_UNSUCCESSFUL, EINVAL},
- {NT_STATUS_NOT_IMPLEMENTED, ENOSYS},
- {NT_STATUS_IN_PAGE_ERROR, EFAULT},
- {NT_STATUS_BAD_NETWORK_NAME, ENOENT},
-#ifdef EDQUOT
- {NT_STATUS_PAGEFILE_QUOTA, EDQUOT},
- {NT_STATUS_QUOTA_EXCEEDED, EDQUOT},
- {NT_STATUS_REGISTRY_QUOTA_LIMIT, EDQUOT},
- {NT_STATUS_LICENSE_QUOTA_EXCEEDED, EDQUOT},
-#endif
-#ifdef ETIME
- {NT_STATUS_TIMER_NOT_CANCELED, ETIME},
-#endif
- {NT_STATUS_INVALID_PARAMETER, EINVAL},
- {NT_STATUS_NO_SUCH_DEVICE, ENODEV},
- {NT_STATUS_NO_SUCH_FILE, ENOENT},
-#ifdef ENODATA
- {NT_STATUS_END_OF_FILE, ENODATA},
-#endif
-#ifdef ENOMEDIUM
- {NT_STATUS_NO_MEDIA_IN_DEVICE, ENOMEDIUM},
- {NT_STATUS_NO_MEDIA, ENOMEDIUM},
-#endif
- {NT_STATUS_NONEXISTENT_SECTOR, ESPIPE},
- {NT_STATUS_NO_MEMORY, ENOMEM},
- {NT_STATUS_CONFLICTING_ADDRESSES, EADDRINUSE},
- {NT_STATUS_NOT_MAPPED_VIEW, EINVAL},
- {NT_STATUS_UNABLE_TO_FREE_VM, EADDRINUSE},
- {NT_STATUS_ACCESS_DENIED, EACCES},
- {NT_STATUS_BUFFER_TOO_SMALL, ENOBUFS},
- {NT_STATUS_WRONG_PASSWORD, EACCES},
- {NT_STATUS_LOGON_FAILURE, EACCES},
- {NT_STATUS_INVALID_WORKSTATION, EACCES},
- {NT_STATUS_INVALID_LOGON_HOURS, EACCES},
- {NT_STATUS_PASSWORD_EXPIRED, EACCES},
- {NT_STATUS_ACCOUNT_DISABLED, EACCES},
- {NT_STATUS_DISK_FULL, ENOSPC},
- {NT_STATUS_INVALID_PIPE_STATE, EPIPE},
- {NT_STATUS_PIPE_BUSY, EPIPE},
- {NT_STATUS_PIPE_DISCONNECTED, EPIPE},
- {NT_STATUS_PIPE_NOT_AVAILABLE, ENOSYS},
- {NT_STATUS_FILE_IS_A_DIRECTORY, EISDIR},
- {NT_STATUS_NOT_SUPPORTED, ENOSYS},
- {NT_STATUS_NOT_A_DIRECTORY, ENOTDIR},
- {NT_STATUS_DIRECTORY_NOT_EMPTY, ENOTEMPTY},
- {NT_STATUS_NETWORK_UNREACHABLE, ENETUNREACH},
- {NT_STATUS_HOST_UNREACHABLE, EHOSTUNREACH},
- {NT_STATUS_CONNECTION_ABORTED, ECONNABORTED},
- {NT_STATUS_CONNECTION_REFUSED, ECONNREFUSED},
- {NT_STATUS_TOO_MANY_LINKS, EMLINK},
- {NT_STATUS_NETWORK_BUSY, EBUSY},
- {NT_STATUS_DEVICE_DOES_NOT_EXIST, ENODEV},
-#ifdef ELIBACC
- {NT_STATUS_DLL_NOT_FOUND, ELIBACC},
-#endif
- {NT_STATUS_PIPE_BROKEN, EPIPE},
- {NT_STATUS_REMOTE_NOT_LISTENING, ECONNREFUSED},
- {NT_STATUS_NETWORK_ACCESS_DENIED, EACCES},
- {NT_STATUS_TOO_MANY_OPENED_FILES, EMFILE},
-#ifdef EPROTO
- {NT_STATUS_DEVICE_PROTOCOL_ERROR, EPROTO},
-#endif
- {NT_STATUS_FLOAT_OVERFLOW, ERANGE},
- {NT_STATUS_FLOAT_UNDERFLOW, ERANGE},
- {NT_STATUS_INTEGER_OVERFLOW, ERANGE},
- {NT_STATUS_MEDIA_WRITE_PROTECTED, EROFS},
- {NT_STATUS_PIPE_CONNECTED, EISCONN},
- {NT_STATUS_MEMORY_NOT_ALLOCATED, EFAULT},
- {NT_STATUS_FLOAT_INEXACT_RESULT, ERANGE},
- {NT_STATUS_ILL_FORMED_PASSWORD, EACCES},
- {NT_STATUS_PASSWORD_RESTRICTION, EACCES},
- {NT_STATUS_ACCOUNT_RESTRICTION, EACCES},
- {NT_STATUS_PORT_CONNECTION_REFUSED, ECONNREFUSED},
- {NT_STATUS_NAME_TOO_LONG, ENAMETOOLONG},
- {NT_STATUS_REMOTE_DISCONNECT, ESHUTDOWN},
- {NT_STATUS_CONNECTION_DISCONNECTED, ECONNABORTED},
- {NT_STATUS_CONNECTION_RESET, ENETRESET},
-#ifdef ENOTUNIQ
- {NT_STATUS_IP_ADDRESS_CONFLICT1, ENOTUNIQ},
- {NT_STATUS_IP_ADDRESS_CONFLICT2, ENOTUNIQ},
-#endif
- {NT_STATUS_PORT_MESSAGE_TOO_LONG, EMSGSIZE},
- {NT_STATUS_PROTOCOL_UNREACHABLE, ENOPROTOOPT},
- {NT_STATUS_ADDRESS_ALREADY_EXISTS, EADDRINUSE},
- {NT_STATUS_PORT_UNREACHABLE, EHOSTUNREACH},
- {NT_STATUS_IO_TIMEOUT, ETIMEDOUT},
- {NT_STATUS_RETRY, EAGAIN},
-#ifdef ENOTUNIQ
- {NT_STATUS_DUPLICATE_NAME, ENOTUNIQ},
-#endif
-#ifdef ECOMM
- {NT_STATUS_NET_WRITE_FAULT, ECOMM},
-#endif
-#ifdef EXDEV
- {NT_STATUS_NOT_SAME_DEVICE, EXDEV},
-#endif
- {NT_STATUS(0), 0}
-};
-
-/****************************************************************************
- The following mappings need tidying up and moving into libsmb/errormap.c...
-****************************************************************************/
-
-static int cli_errno_from_nt(NTSTATUS status)
-{
- int i;
- DEBUG(10,("cli_errno_from_nt: 32 bit codes: code=%08x\n", NT_STATUS_V(status)));
-
- /* Status codes without this bit set are not errors */
-
- if (!(NT_STATUS_V(status) & 0xc0000000)) {
- return 0;
- }
-
- for (i=0;nt_errno_map[i].error;i++) {
- if (NT_STATUS_V(nt_errno_map[i].status) ==
- NT_STATUS_V(status)) return nt_errno_map[i].error;
- }
-
- /* for all other cases - a default code */
- return EINVAL;
-}
/* Return a UNIX errno appropriate for the error received in the last
packet. */
@@ -382,7 +246,7 @@ int cli_errno(struct cli_state *cli)
if (cli_is_nt_error(cli)) {
status = cli_nt_error(cli);
- return cli_errno_from_nt(status);
+ return map_errno_from_nt_status(status);
}
if (cli_is_dos_error(cli)) {
@@ -391,7 +255,7 @@ int cli_errno(struct cli_state *cli)
cli_dos_error(cli, &eclass, &ecode);
status = dos_to_ntstatus(eclass, ecode);
- return cli_errno_from_nt(status);
+ return map_errno_from_nt_status(status);
}
/*
diff --git a/source3/m4/check_path.m4 b/source3/m4/check_path.m4
index 7aa8c213e0..40a97d3674 100644
--- a/source3/m4/check_path.m4
+++ b/source3/m4/check_path.m4
@@ -18,6 +18,7 @@ AC_PREFIX_DEFAULT(/usr/local/samba)
rootsbindir="\${SBINDIR}"
lockdir="\${VARDIR}/locks"
piddir="\${VARDIR}/locks"
+ncalrpcdir="\${VARDIR}/ncalrpc"
test "${mandir}" || mandir="\${prefix}/man"
logfilebase="\${VARDIR}"
privatedir="\${prefix}/private"
@@ -46,6 +47,7 @@ AC_ARG_WITH(fhs,
codepagedir="\${MODULESDIR}"
statedir="\${VARDIR}/lib/samba"
cachedir="\${VARDIR}/lib/samba"
+ ncalrpcdir="\${VARDIR}/ncalrpc"
AC_DEFINE(FHS_COMPATIBLE, 1, [Whether to use fully FHS-compatible paths])
;;
esac])
@@ -115,6 +117,22 @@ AC_ARG_WITH(piddir,
esac])
#################################################
+# set ncalrpc directory location
+AC_ARG_WITH(ncalprcdir,
+[AS_HELP_STRING([--with-ncalprcdir=DIR], [Where to put ncalrpc sockets ($ac_default_prefix/var/ncalrpc)])],
+[ case "$withval" in
+ yes|no)
+ #
+ # Just in case anybody calls it without argument
+ #
+ AC_MSG_WARN([--with-ncalrpcdir called without argument - will use default])
+ ;;
+ * )
+ ncalrpcdir="$withval"
+ ;;
+ esac])
+
+#################################################
# set SWAT directory location
AC_ARG_WITH(swatdir,
[AS_HELP_STRING([--with-swatdir=DIR], [Where to put SWAT files ($ac_default_prefix/swat)])],
@@ -227,6 +245,7 @@ AC_ARG_WITH(mandir,
AC_SUBST(configdir)
AC_SUBST(lockdir)
AC_SUBST(piddir)
+AC_SUBST(ncalrpcdir)
AC_SUBST(logfilebase)
AC_SUBST(ctdbdir)
AC_SUBST(privatedir)
diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c
index a2f3477b76..80e44e51fc 100644
--- a/source3/modules/vfs_acl_xattr.c
+++ b/source3/modules/vfs_acl_xattr.c
@@ -133,26 +133,6 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
return NT_STATUS_OK;
}
-static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t mode)
-{
- return SMB_VFS_NEXT_MKDIR(handle, path, mode);
-}
-
-static int rmdir_acl_xattr(vfs_handle_struct *handle, const char *path)
-{
- return SMB_VFS_NEXT_RMDIR(handle, path);
-}
-
-static int open_acl_xattr(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
-{
- return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
-}
-
-static int unlink_acl_xattr(vfs_handle_struct *handle, const char *fname)
-{
- return SMB_VFS_NEXT_UNLINK(handle, fname);
-}
-
static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
files_struct *fsp,
const char *name,
@@ -198,6 +178,42 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
return status;
}
+static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t mode)
+{
+ return SMB_VFS_NEXT_MKDIR(handle, path, mode);
+}
+
+/*********************************************************************
+ * Currently this only works for existing files. Need to work on
+ * inheritance for new files.
+*********************************************************************/
+
+static int open_acl_xattr(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode)
+{
+ uint32_t access_granted = 0;
+ SEC_DESC *pdesc = NULL;
+ NTSTATUS status = get_nt_acl_xattr_internal(handle,
+ NULL,
+ fname,
+ (OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION),
+ &pdesc);
+ if (NT_STATUS_IS_OK(status)) {
+ /* See if we can access it. */
+ if (!se_access_check(pdesc,
+ handle->conn->server_info->ptok,
+ fsp->access_mask,
+ &access_granted,
+ &status)) {
+ errno = map_errno_from_nt_status(status);
+ return -1;
+ }
+ }
+
+ return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+}
+
static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
uint32 security_info, SEC_DESC **ppdesc)
{
@@ -312,9 +328,7 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
static vfs_op_tuple skel_op_tuples[] =
{
{SMB_VFS_OP(mkdir_acl_xattr), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(rmdir_acl_xattr), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(open_acl_xattr), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(unlink_acl_xattr),SMB_VFS_OP_UNLINK,SMB_VFS_LAYER_TRANSPARENT},
/* NT File ACL operations */
diff --git a/source3/modules/vfs_smb_traffic_analyzer.c b/source3/modules/vfs_smb_traffic_analyzer.c
index ff61768495..9b4c1b3e25 100644
--- a/source3/modules/vfs_smb_traffic_analyzer.c
+++ b/source3/modules/vfs_smb_traffic_analyzer.c
@@ -156,6 +156,7 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
{
struct refcounted_sock *rf_sock = NULL;
struct timeval tv;
+ time_t tv_sec;
struct tm *tm = NULL;
int seconds;
char *str = NULL;
@@ -170,7 +171,8 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
}
GetTimeOfDay(&tv);
- tm=localtime(&tv.tv_sec);
+ tv_sec = convert_timespec_to_time_t(convert_timeval_to_timespec(tv));
+ tm = localtime(&tv_sec);
if (!tm) {
return;
}
diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c
index 4527ae7127..306d4d0a35 100644
--- a/source3/passdb/secrets.c
+++ b/source3/passdb/secrets.c
@@ -259,6 +259,31 @@ bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
return True;
}
+bool secrets_store_local_schannel_key(uint8_t schannel_key[16])
+{
+ return secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, schannel_key, 16);
+}
+
+bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16])
+{
+ size_t size = 0;
+ uint8_t *key;
+
+ key = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, &size);
+ if (key == NULL) {
+ return false;
+ }
+
+ if (size != 16) {
+ SAFE_FREE(key);
+ return false;
+ }
+
+ memcpy(schannel_key, key, 16);
+ SAFE_FREE(key);
+ return true;
+}
+
/**
* Form a key for fetching the machine trust account sec channel type
*
diff --git a/source3/winbindd/idmap_adex/domain_util.c b/source3/winbindd/idmap_adex/domain_util.c
index ab31ccef7a..6851503cc8 100644
--- a/source3/winbindd/idmap_adex/domain_util.c
+++ b/source3/winbindd/idmap_adex/domain_util.c
@@ -49,6 +49,12 @@ static NTSTATUS dc_add_domain(const char *domain)
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct dc_info *dc = NULL;
+ if (!domain) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ DEBUG(10,("dc_add_domain: Attempting to add domain %s\n", domain));
+
/* Check for duplicates */
dc = dc_list_head();
@@ -73,6 +79,8 @@ static NTSTATUS dc_add_domain(const char *domain)
nt_status = NT_STATUS_OK;
+ DEBUG(5,("dc_add_domain: Successfully added %s\n", domain));
+
done:
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_destroy(dc);
diff --git a/source3/winbindd/idmap_adex/likewise_cell.c b/source3/winbindd/idmap_adex/likewise_cell.c
index 77eeee406b..7723b3e015 100644
--- a/source3/winbindd/idmap_adex/likewise_cell.c
+++ b/source3/winbindd/idmap_adex/likewise_cell.c
@@ -389,6 +389,24 @@ done:
status = ads_do_search(c->conn, search_base,
scope, expr, attrs, msg);
if (ADS_ERR_OK(status)) {
+ if (DEBUGLEVEL >= 10) {
+ LDAPMessage *e = NULL;
+
+ int n = ads_count_replies(c->conn, *msg);
+
+ DEBUG(10,("cell_do_search: Located %d entries\n", n));
+
+ for (e=ads_first_entry(c->conn, *msg);
+ e!=NULL;
+ e = ads_next_entry(c->conn, e))
+ {
+ char *dn = ads_get_dn(c->conn, e);
+
+ DEBUGADD(10,(" dn: %s\n", dn ? dn : "<NULL>"));
+ SAFE_FREE(dn);
+ }
+ }
+
return status;
}
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 1600f05eb1..f6a9c1f26d 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -120,6 +120,10 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
SMB_ASSERT(continuation != NULL);
+ DEBUG(10, ("Sending request to child pid %d (domain=%s)\n",
+ (int)child->pid,
+ (child->domain != NULL) ? child->domain->name : "''"));
+
state = TALLOC_P(mem_ctx, struct winbindd_async_request);
if (state == NULL) {
diff --git a/source4/auth/gensec/gensec.c b/source4/auth/gensec/gensec.c
index 0edb34d740..5d57383d2a 100644
--- a/source4/auth/gensec/gensec.c
+++ b/source4/auth/gensec/gensec.c
@@ -490,6 +490,7 @@ static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
(*gensec_security)->ops = NULL;
+ (*gensec_security)->private_data = NULL;
ZERO_STRUCT((*gensec_security)->target);
ZERO_STRUCT((*gensec_security)->peer_addr);
@@ -525,6 +526,7 @@ _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
(*gensec_security)->private_data = NULL;
(*gensec_security)->subcontext = true;
+ (*gensec_security)->want_features = parent->want_features;
(*gensec_security)->event_ctx = parent->event_ctx;
(*gensec_security)->msg_ctx = parent->msg_ctx;
(*gensec_security)->lp_ctx = parent->lp_ctx;
@@ -1015,7 +1017,11 @@ _PUBLIC_ NTSTATUS gensec_update_recv(struct gensec_update_request *req, TALLOC_C
_PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
uint32_t feature)
{
- gensec_security->want_features |= feature;
+ if (!gensec_security->ops || !gensec_security->ops->want_feature) {
+ gensec_security->want_features |= feature;
+ return;
+ }
+ gensec_security->ops->want_feature(gensec_security, feature);
}
/**
diff --git a/source4/auth/gensec/gensec.h b/source4/auth/gensec/gensec.h
index 84fc26d127..0b31882ddd 100644
--- a/source4/auth/gensec/gensec.h
+++ b/source4/auth/gensec/gensec.h
@@ -133,6 +133,8 @@ struct gensec_security_ops {
NTSTATUS (*session_key)(struct gensec_security *gensec_security, DATA_BLOB *session_key);
NTSTATUS (*session_info)(struct gensec_security *gensec_security,
struct auth_session_info **session_info);
+ void (*want_feature)(struct gensec_security *gensec_security,
+ uint32_t feature);
bool (*have_feature)(struct gensec_security *gensec_security,
uint32_t feature);
bool enabled;
diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c
index 1855e0583d..bf991616bd 100644
--- a/source4/auth/gensec/spnego.c
+++ b/source4/auth/gensec/spnego.c
@@ -1094,6 +1094,20 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
return NT_STATUS_INVALID_PARAMETER;
}
+static void gensec_spnego_want_feature(struct gensec_security *gensec_security,
+ uint32_t feature)
+{
+ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data;
+
+ if (!spnego_state || !spnego_state->sub_sec_security) {
+ gensec_security->want_features |= feature;
+ return;
+ }
+
+ gensec_want_feature(spnego_state->sub_sec_security,
+ feature);
+}
+
static bool gensec_spnego_have_feature(struct gensec_security *gensec_security,
uint32_t feature)
{
@@ -1133,6 +1147,7 @@ static const struct gensec_security_ops gensec_spnego_security_ops = {
.unwrap_packets = gensec_spnego_unwrap_packets,
.session_key = gensec_spnego_session_key,
.session_info = gensec_spnego_session_info,
+ .want_feature = gensec_spnego_want_feature,
.have_feature = gensec_spnego_have_feature,
.enabled = true,
.priority = GENSEC_SPNEGO
diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c
index e02e8d81a6..ca87159c58 100644
--- a/source4/dsdb/samdb/cracknames.c
+++ b/source4/dsdb/samdb/cracknames.c
@@ -356,15 +356,7 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
const char *result_filter = NULL;
struct ldb_dn *name_dn = NULL;
- struct smb_krb5_context *smb_krb5_context;
- ret = smb_krb5_init_context(mem_ctx,
- ldb_get_event_context(sam_ctx),
- (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
- &smb_krb5_context);
-
- if (ret) {
- return WERR_NOMEM;
- }
+ struct smb_krb5_context *smb_krb5_context = NULL;
info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
info1->dns_domain_name = NULL;
@@ -380,6 +372,30 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
/* here we need to set the domain_filter and/or the result_filter */
switch (format_offered) {
+ case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:
+ {
+ int i;
+ enum drsuapi_DsNameFormat formats[] = {
+ DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
+ DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, DRSUAPI_DS_NAME_FORMAT_CANONICAL,
+ DRSUAPI_DS_NAME_FORMAT_GUID, DRSUAPI_DS_NAME_FORMAT_DISPLAY,
+ DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
+ DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
+ DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX
+ };
+ WERROR werr;
+ for (i=0; i < ARRAY_SIZE(formats); i++) {
+ werr = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, formats[i], format_desired, name, info1);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+ if (info1->status != DRSUAPI_DS_NAME_STATUS_NOT_FOUND) {
+ return werr;
+ }
+ }
+ return werr;
+ }
+
case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
{
@@ -534,6 +550,16 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: {
krb5_principal principal;
char *unparsed_name;
+
+ ret = smb_krb5_init_context(mem_ctx,
+ ldb_get_event_context(sam_ctx),
+ (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
+ &smb_krb5_context);
+
+ if (ret) {
+ return WERR_NOMEM;
+ }
+
ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
if (ret) {
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
@@ -560,6 +586,16 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
krb5_principal principal;
char *unparsed_name_short;
char *service;
+
+ ret = smb_krb5_init_context(mem_ctx,
+ ldb_get_event_context(sam_ctx),
+ (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
+ &smb_krb5_context);
+
+ if (ret) {
+ return WERR_NOMEM;
+ }
+
ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
if (ret == 0 && principal->name.name_string.len < 2) {
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
@@ -1265,7 +1301,7 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx,
const char **nt4_domain,
const char **nt4_account)
{
- uint32_t format_offered = DRSUAPI_DS_NAME_FORMAT_UKNOWN;
+ uint32_t format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN;
/* Handle anonymous bind */
if (!name || !*name) {
@@ -1282,6 +1318,8 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx,
format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
} else if (strchr_m(name, '/')) {
format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
+ } else {
+ return NT_STATUS_NO_SUCH_USER;
}
return crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, format_offered, name, nt4_domain, nt4_account);
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 8e4483a78e..b452b66d56 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -589,7 +589,6 @@ static int partition_delete(struct ldb_module *module, struct ldb_request *req)
/* rename */
static int partition_rename(struct ldb_module *module, struct ldb_request *req)
{
- int i, matched = -1;
/* Find backend */
struct dsdb_control_current_partition *backend, *backend2;
@@ -619,22 +618,6 @@ static int partition_rename(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
}
- for (i=0; data && data->partitions && data->partitions[i]; i++) {
- if (ldb_dn_compare_base(data->partitions[i]->dn, req->op.rename.olddn) == 0) {
- matched = i;
- }
- }
-
- if (matched > 0) {
- ldb_asprintf_errstring(module->ldb,
- "Cannot rename from %s to %s, subtree rename would cross partition %s: %s",
- ldb_dn_get_linearized(req->op.rename.olddn),
- ldb_dn_get_linearized(req->op.rename.newdn),
- ldb_dn_get_linearized(data->partitions[matched]->dn),
- ldb_strerror(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
- return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
- }
-
return partition_replicate(module, req, req->op.rename.olddn);
}
diff --git a/source4/dsdb/schema/schema_description.c b/source4/dsdb/schema/schema_description.c
index 6884c5284e..c3c37b4653 100644
--- a/source4/dsdb/schema/schema_description.c
+++ b/source4/dsdb/schema/schema_description.c
@@ -33,7 +33,6 @@ char *schema_attribute_description(TALLOC_CTX *mem_ctx,
const char *seperator,
const char *oid,
const char *name,
- const char *description,
const char *equality,
const char *substring,
const char *syntax,
@@ -46,15 +45,6 @@ char *schema_attribute_description(TALLOC_CTX *mem_ctx,
"NAME '%s'%s", name, seperator);
IF_NULL_FAIL_RET(schema_entry);
- if (description) {
-#if 0
- /* Need a way to escape ' characters from the description */
- schema_entry = talloc_asprintf_append(schema_entry,
- "DESC '%s'%s", description, seperator);
- IF_NULL_FAIL_RET(schema_entry);
-#endif
- }
-
if (equality) {
schema_entry = talloc_asprintf_append(schema_entry,
"EQUALITY %s%s", equality, seperator);
@@ -104,7 +94,7 @@ char *schema_attribute_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_att
" ",
attribute->attributeID_oid,
attribute->lDAPDisplayName,
- NULL, NULL, NULL, talloc_asprintf(tmp_ctx, "'%s'", syntax),
+ NULL, NULL, talloc_asprintf(tmp_ctx, "'%s'", syntax),
attribute->isSingleValued,
attribute->systemOnly);
talloc_free(tmp_ctx);
@@ -149,7 +139,6 @@ char *schema_class_description(TALLOC_CTX *mem_ctx,
const char *oid,
const char *name,
const char **auxillary_classes,
- const char *description,
const char *subClassOf,
int objectClassCategory,
char **must,
@@ -164,12 +153,6 @@ char *schema_class_description(TALLOC_CTX *mem_ctx,
"NAME '%s'%s", name, seperator);
IF_NULL_FAIL_RET(schema_entry);
- if (description) {
- schema_entry = talloc_asprintf_append(schema_entry,
- "DESC '%s'%s", description, seperator);
- IF_NULL_FAIL_RET(schema_entry);
- }
-
if (auxillary_classes) {
schema_entry = talloc_asprintf_append(schema_entry,
"AUX ( ");
@@ -262,7 +245,6 @@ char *schema_class_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_class *
" ",
class->governsID_oid,
class->lDAPDisplayName,
- NULL,
NULL,
class->subClassOf,
class->objectClassCategory,
@@ -308,8 +290,11 @@ char *schema_class_to_dITContentRule(TALLOC_CTX *mem_ctx, const struct dsdb_clas
class->governsID_oid,
class->lDAPDisplayName,
(const char **)aux_class_list,
- NULL,
- class->subClassOf,
+ NULL, /* Must not specify a
+ * SUP (subclass) in
+ * ditContentRules
+ * per MS-ADTS
+ * 3.1.1.3.1.1.1 */
-1, must_attr_list, may_attr_list);
talloc_free(tmp_ctx);
return schema_description;
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c
index 19dff5e01d..d557da2a5b 100644
--- a/source4/heimdal/kdc/krb5tgs.c
+++ b/source4/heimdal/kdc/krb5tgs.c
@@ -1393,6 +1393,8 @@ tgs_build_reply(krb5_context context,
char opt_str[128];
int signedpath = 0;
+ Key *tkey;
+
memset(&sessionkey, 0, sizeof(sessionkey));
memset(&adtkt, 0, sizeof(adtkt));
krb5_data_zero(&rspac);
@@ -1630,26 +1632,22 @@ server_lookup:
}
/* check PAC if not cross realm and if there is one */
- if (!cross_realm) {
- Key *tkey;
-
- ret = hdb_enctype2key(context, &krbtgt->entry,
- krbtgt_etype, &tkey);
- if(ret) {
- kdc_log(context, config, 0,
+ ret = hdb_enctype2key(context, &krbtgt->entry,
+ krbtgt_etype, &tkey);
+ if(ret) {
+ kdc_log(context, config, 0,
"Failed to find key for krbtgt PAC check");
- goto out;
- }
+ goto out;
+ }
- ret = check_PAC(context, config, cp,
- client, server, ekey, &tkey->key,
- tgt, &rspac, &signedpath);
- if (ret) {
- kdc_log(context, config, 0,
- "Verify PAC failed for %s (%s) from %s with %s",
- spn, cpn, from, krb5_get_err_text(context, ret));
- goto out;
- }
+ ret = check_PAC(context, config, cp,
+ client, server, ekey, &tkey->key,
+ tgt, &rspac, &signedpath);
+ if (ret) {
+ kdc_log(context, config, 0,
+ "Verify PAC failed for %s (%s) from %s with %s",
+ spn, cpn, from, krb5_get_err_text(context, ret));
+ goto out;
}
/* also check the krbtgt for signature */
diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c
index d7317f17d4..51f464cd09 100644
--- a/source4/kdc/hdb-samba4.c
+++ b/source4/kdc/hdb-samba4.c
@@ -757,13 +757,20 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db,
goto out;
}
- ndr_err = ndr_pull_struct_blob_all(password_val, mem_ctx, private->iconv_convenience, &password_blob,
+ ndr_err = ndr_pull_struct_blob(password_val, mem_ctx, private->iconv_convenience, &password_blob,
(ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
ret = EINVAL;
goto out;
}
+ entry_ex->entry.kvno = -1;
+ for (i=0; i < password_blob.count; i++) {
+ if (password_blob.current->array[i].AuthType == TRUST_AUTH_TYPE_VERSION) {
+ entry_ex->entry.kvno = password_blob.current->array[i].AuthInfo.version.version;
+ }
+ }
+
for (i=0; i < password_blob.count; i++) {
if (password_blob.current->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
password_utf16 = data_blob_const(password_blob.current->array[i].AuthInfo.clear.password,
@@ -806,6 +813,8 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db,
entry_ex->entry.keys.len++;
}
+ entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal)));
+
ret = copy_Principal(principal, entry_ex->entry.principal);
if (ret) {
krb5_clear_error_string(context);
@@ -1148,7 +1157,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
principal, HDB_SAMBA4_ENT_TYPE_KRBTGT,
msg[0], realm_ref_msg_1[0], entry_ex);
if (ret != 0) {
- krb5_warnx(context, "LDB_fetch: message2entry failed");
+ krb5_warnx(context, "LDB_fetch: self krbtgt message2entry failed");
}
return ret;
@@ -1186,7 +1195,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
principal, direction,
msg[0], entry_ex);
if (ret != 0) {
- krb5_warnx(context, "LDB_fetch: message2entry failed");
+ krb5_warnx(context, "LDB_fetch: trust_message2entry failed");
}
return ret;
diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl
index 31fe8a359e..4274d2000a 100644
--- a/source4/librpc/idl/drsblobs.idl
+++ b/source4/librpc/idl/drsblobs.idl
@@ -409,21 +409,23 @@ interface drsblobs {
[size_is(1)] AuthenticationInformation array[];
} AuthenticationInformationArray;
+ /* This is nopull,nopush because we pass count down to the
+ * manual parser of AuthenticationInformationArray */
typedef [public,nopull,nopush,noprint,gensize] struct {
uint32 count;
[relative] AuthenticationInformationArray *current;
[relative] AuthenticationInformationArray *previous;
} trustAuthInOutBlob;
+ void decode_trustAuthInOut(
+ [in] trustAuthInOutBlob blob
+ );
+
typedef [public,gensize] struct {
uint32 count;
[relative] AuthenticationInformation *current[count];
} trustCurrentPasswords;
- void decode_trustAuthInOut(
- [in] trustAuthInOutBlob blob
- );
-
typedef [public,nopull] struct {
uint8 confounder[512];
[subcontext(0),subcontext_size(outgoing_size)] trustCurrentPasswords outgoing;
diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl
index 76858b2d5c..a41bc9cf19 100644
--- a/source4/librpc/idl/drsuapi.idl
+++ b/source4/librpc/idl/drsuapi.idl
@@ -877,7 +877,7 @@ interface drsuapi
} drsuapi_DsNameFlags;
typedef [v1_enum] enum {
- DRSUAPI_DS_NAME_FORMAT_UKNOWN = 0,
+ DRSUAPI_DS_NAME_FORMAT_UNKNOWN = 0,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 = 1,
DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT = 2,
DRSUAPI_DS_NAME_FORMAT_DISPLAY = 3,
diff --git a/source4/librpc/idl/misc.idl b/source4/librpc/idl/misc.idl
index 8331977398..791b86466c 100644
--- a/source4/librpc/idl/misc.idl
+++ b/source4/librpc/idl/misc.idl
@@ -30,9 +30,11 @@ interface misc
/* Only SEC_CHAN_WKSTA can forward requests to other domains. */
typedef [public] enum {
- SEC_CHAN_WKSTA = 2,
- SEC_CHAN_DOMAIN = 4,
- SEC_CHAN_BDC = 6
+ SEC_CHAN_NULL = 0,
+ SEC_CHAN_WKSTA = 2,
+ SEC_CHAN_DNS_DOMAIN = 3,
+ SEC_CHAN_DOMAIN = 4,
+ SEC_CHAN_BDC = 6
} netr_SchannelType;
/* SAM database types */
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 52d5631cfd..bef7e4be78 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -95,6 +95,10 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
return false;
}
+ if (call->conn->state_flags & DCESRV_CALL_STATE_FLAG_HEADER_SIGNING) {
+ gensec_want_feature(auth->gensec_security, GENSEC_FEATURE_SIGN_PKT_HEADER);
+ }
+
return true;
}
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index 5e3be84cc5..836fd8dc62 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -727,13 +727,46 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return NT_STATUS_INVALID_PARAMETER;
}
+
+ if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
+ if (auth_struct.incoming.count > 1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
}
if (auth_struct.incoming.count) {
+ int i;
+ struct trustAuthInOutBlob incoming;
+
+ incoming.count = auth_struct.incoming.count;
+ incoming.current = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!incoming.current) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ incoming.current->array = *auth_struct.incoming.current;
+ if (!incoming.current->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ incoming.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!incoming.previous) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ incoming.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, incoming.count);
+ if (!incoming.previous->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < incoming.count; i++) {
+ incoming.previous->array[i].LastUpdateTime = 0;
+ incoming.previous->array[i].AuthType = 0;
+ }
ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx,
lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
- &auth_struct.incoming,
- (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
+ &incoming,
+ (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -742,10 +775,37 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
}
if (auth_struct.outgoing.count) {
+ int i;
+ struct trustAuthInOutBlob outgoing;
+
+ outgoing.count = auth_struct.outgoing.count;
+ outgoing.current = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!outgoing.current) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ outgoing.current->array = *auth_struct.outgoing.current;
+ if (!outgoing.current->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ outgoing.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!outgoing.previous) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ outgoing.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, outgoing.count);
+ if (!outgoing.previous->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < outgoing.count; i++) {
+ outgoing.previous->array[i].LastUpdateTime = 0;
+ outgoing.previous->array[i].AuthType = 0;
+ }
ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx,
lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
- &auth_struct.outgoing,
- (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
+ &outgoing,
+ (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return NT_STATUS_INVALID_PARAMETER;
}
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index d5f7d2afae..b948d1210e 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -87,6 +87,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
const char *attrs[] = {"unicodePwd", "userAccountControl",
"objectSid", NULL};
+ const char *trust_dom_attrs[] = {"flatname", NULL};
+ const char *account_name;
+
ZERO_STRUCTP(r->out.credentials);
*r->out.rid = 0;
*r->out.negotiate_flags = *r->in.negotiate_flags;
@@ -101,10 +104,54 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
+
+ if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
+ char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
+ char *flatname;
+ if (!encoded_account) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Kill the trailing dot */
+ if (encoded_account[strlen(encoded_account)-1] == '.') {
+ encoded_account[strlen(encoded_account)-1] = '\0';
+ }
+
+ /* pull the user attributes */
+ num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, trust_dom_attrs,
+ "(&(trustPartner=%s)(objectclass=trustedDomain))",
+ encoded_account);
+
+ if (num_records == 0) {
+ DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
+ encoded_account));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (num_records > 1) {
+ DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
+ if (!flatname) {
+ /* No flatname for this trust - we can't proceed */
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
+
+ if (!account_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ } else {
+ account_name = r->in.account_name;
+ }
+
/* pull the user attributes */
num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
"(&(sAMAccountName=%s)(objectclass=user))",
- r->in.account_name);
+ ldb_binary_encode_string(mem_ctx, account_name));
if (num_records == 0) {
DEBUG(3,("Couldn't find user [%s] in samdb.\n",
@@ -130,7 +177,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
return NT_STATUS_ACCESS_DENIED;
}
- } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN) {
+ } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
+ r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
diff --git a/source4/torture/rpc/drsuapi_cracknames.c b/source4/torture/rpc/drsuapi_cracknames.c
index fbda69df57..a9a614953d 100644
--- a/source4/torture/rpc/drsuapi_cracknames.c
+++ b/source4/torture/rpc/drsuapi_cracknames.c
@@ -39,6 +39,7 @@ static bool test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
bool ret = true;
struct drsuapi_DsCrackNames r;
enum drsuapi_DsNameFormat formats[] = {
+ DRSUAPI_DS_NAME_FORMAT_UNKNOWN,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
DRSUAPI_DS_NAME_FORMAT_DISPLAY,
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index efbdecab13..245ed1e41b 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -1899,7 +1899,11 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
/* NO_MORE_ENTRIES is allowed */
if (NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES)) {
- return true;
+ if (domains.count == 0) {
+ return true;
+ }
+ printf("EnumTrustDom failed - should have returned 0 trusted domains with 'NT_STATUS_NO_MORE_ENTRIES'\n");
+ return false;
} else if (NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)) {
/* Windows 2003 gets this off by one on the first run */
if (r.out.domains->count < 3 || r.out.domains->count > 4) {
@@ -1950,7 +1954,11 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
/* NO_MORE_ENTRIES is allowed */
if (NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES)) {
- return true;
+ if (domains_ex.count == 0) {
+ return true;
+ }
+ printf("EnumTrustDomainsEx failed - should have returned 0 trusted domains with 'NT_STATUS_NO_MORE_ENTRIES'\n");
+ return false;
} else if (NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)) {
/* Windows 2003 gets this off by one on the first run */
if (r_ex.out.domains->count < 3 || r_ex.out.domains->count > 4) {
@@ -2115,7 +2123,7 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p,
/* Try different trust types too */
- /* 1 == downleven (NT4), 2 == uplevel (ADS), 3 == MIT (kerberos but not AD) */
+ /* 1 == downlevel (NT4), 2 == uplevel (ADS), 3 == MIT (kerberos but not AD) */
trustinfo.trust_type = (((i / 3) + 1) % 3) + 1;
trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION;
@@ -2160,6 +2168,7 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p,
printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status));
ret = false;
} else if (!q.out.info) {
+ printf("QueryTrustedDomainInfo level 1 failed to return an info pointer\n");
ret = false;
} else {
if (strcmp(q.out.info->info_ex.netbios_name.string, trustinfo.netbios_name.string) != 0) {
@@ -2188,11 +2197,13 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p,
/* now that we have some domains to look over, we can test the enum calls */
if (!test_EnumTrustDom(p, mem_ctx, handle)) {
+ printf("test_EnumTrustDom failed\n");
ret = false;
}
for (i=0; i<12; i++) {
if (!test_DeleteTrustedDomainBySid(p, mem_ctx, handle, domsid[i])) {
+ printf("test_DeleteTrustedDomainBySid failed\n");
ret = false;
}
}
diff --git a/source4/utils/ad2oLschema.c b/source4/utils/ad2oLschema.c
index 3c2ffe7a00..c579112b45 100644
--- a/source4/utils/ad2oLschema.c
+++ b/source4/utils/ad2oLschema.c
@@ -221,7 +221,6 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_sch
for (attribute=schema->attributes; attribute; attribute = attribute->next) {
const char *name = attribute->lDAPDisplayName;
- const char *description = attribute->adminDescription;
const char *oid = attribute->attributeID_oid;
const char *syntax = attribute->attributeSyntax_oid;
const char *equality = NULL, *substring = NULL;
@@ -270,7 +269,16 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_sch
}
}
- schema_entry = schema_attribute_description(mem_ctx, target, seperator, oid, name, description, equality, substring, syntax, single_value, false);
+ schema_entry = schema_attribute_description(mem_ctx,
+ target,
+ seperator,
+ oid,
+ name,
+ equality,
+ substring,
+ syntax,
+ single_value,
+ false);
if (schema_entry == NULL) {
ret.failures++;
@@ -291,7 +299,6 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_sch
/* This is already sorted to have 'top' and similar classes first */
for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) {
const char *name = objectclass->lDAPDisplayName;
- const char *description = objectclass->adminDescription;
const char *oid = objectclass->governsID_oid;
const char *subClassOf = objectclass->subClassOf;
int objectClassCategory = objectclass->objectClassCategory;
@@ -356,7 +363,6 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_sch
oid,
name,
NULL,
- description,
subClassOf,
objectClassCategory,
must,
diff --git a/testprogs/blackbox/test_ldb.sh b/testprogs/blackbox/test_ldb.sh
index 1774dbc7a3..5209abeb2c 100755
--- a/testprogs/blackbox/test_ldb.sh
+++ b/testprogs/blackbox/test_ldb.sh
@@ -180,4 +180,29 @@ if [ x"$st" != x"0" ]; then
failed=`expr $failed + $st`
fi
+echo "Getting HEX GUID/SID of $BASEDN"
+HEXDN=`bin/ldbsearch $CONFIGURATION $options -b "$BASEDN" -H $p://$SERVER -s base "(objectClass=*)" --controls=extended_dn:1:0 | grep 'dn: ' | cut -d ' ' -f2-`
+HEXGUID=`echo "$HEXDN" | cut -d ';' -f1`
+HEXSID=`echo "$HEXDN" | cut -d ';' -f2`
+echo "HEXGUID[$HEXGUID]"
+echo "HEXSID[$HEXSID]"
+
+echo "Getting STR GUID/SID of $BASEDN"
+STRDN=`bin/ldbsearch $CONFIGURATION $options -b "$BASEDN" -H $p://$SERVER -s base "(objectClass=*)" --controls=extended_dn:1:1 | grep 'dn: ' | cut -d ' ' -f2-`
+echo "STRDN: $STRDN"
+STRGUID=`echo "$STRDN" | cut -d ';' -f1`
+STRSID=`echo "$STRDN" | cut -d ';' -f2`
+echo "STRGUID[$STRGUID]"
+echo "STRSID[$STRSID]"
+
+SPECIALDNS="$HEXGUID $HEXSID $STRGUID $STRSID"
+for SPDN in $SPECIALDNS; do
+ echo "Search for $SPDN"
+ nentries=`bin/ldbsearch $options $CONFIGURATION -H $p://$SERVER -s base -b "$SPDN" '(objectClass=*)' | grep "dn: $BASEDN" | wc -l`
+ if [ $nentries -lt 1 ]; then
+ echo "Special search returned 0 items"
+ failed=`expr $failed + 1`
+ fi
+done
+
exit $failed