1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-12 09:18:10 +03:00

Merge branch 'master' of git://git.samba.org/samba

This commit is contained in:
Nadezhda Ivanova 2010-01-07 12:34:06 +02:00
commit 309473f938
33 changed files with 2413 additions and 1813 deletions

View File

@ -1,5 +1,6 @@
TALLOC_OBJ = $(tallocdir)/talloc.o
TALLOC_SHLIB = libtalloc.$(SHLIBEXT)
TALLOC_SOLIB = libtalloc.$(SHLIBEXT).$(TALLOC_VERSION)
TALLOC_SONAME = libtalloc.$(SHLIBEXT).$(TALLOC_VERSION_MAJOR)
TALLOC_STLIB = libtalloc.a
@ -25,6 +26,10 @@ install:: all
if [ -f talloc.3 ];then ${INSTALLCMD} -m 644 talloc.3 $(DESTDIR)$(mandir)/man3; fi
which swig >/dev/null 2>&1 && ${INSTALLCMD} -d $(DESTDIR)`swig -swiglib` || true
which swig >/dev/null 2>&1 && ${INSTALLCMD} -m 644 talloc.i $(DESTDIR)`swig -swiglib` || true
rm -f $(DESTDIR)$(libdir)/$(TALLOC_SONAME)
ln -s $(TALLOC_SOLIB) $(DESTDIR)$(libdir)/$(TALLOC_SONAME)
rm -f $(DESTDIR)$(libdir)/$(TALLOC_SHLIB)
ln -s $(TALLOC_SOLIB) $(DESTDIR)$(libdir)/$(TALLOC_SHLIB)
doc:: talloc.3 talloc.3.html

View File

@ -9,6 +9,7 @@ exec_prefix = @exec_prefix@
bindir = @bindir@
includedir = @includedir@
libdir = @libdir@
mandir = @mandir@
VPATH = @srcdir@:@libreplacedir@
srcdir = @srcdir@
builddir = @builddir@

View File

@ -61,9 +61,9 @@ doc:: manpages/tdbbackup.8 manpages/tdbdump.8 manpages/tdbtool.8
-test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
installdocs::
${INSTALLCMD} -d $(DESTDIR)$(mandir)/man1
for I in manpages/*.1; do \
${INSTALLCMD} -m 644 $$I $(DESTDIR)$(mandir)/man1 \
${INSTALLCMD} -d $(DESTDIR)$(mandir)/man8
for I in manpages/*.8; do \
${INSTALLCMD} -m 644 $$I $(DESTDIR)$(mandir)/man8; \
done
install-python:: build-python
@ -91,6 +91,10 @@ installheaders:: installdirs
installlibs:: all installdirs
cp tdb.pc $(DESTDIR)$(libdir)/pkgconfig
cp $(TDB_STLIB) $(TDB_SOLIB) $(DESTDIR)$(libdir)
rm -f $(DESTDIR)$(libdir)/libtdb.$(SHLIBEXT)
ln -s $(TDB_SOLIB) $(DESTDIR)$(libdir)/libtdb.$(SHLIBEXT)
rm -f $(DESTDIR)$(libdir)/$(TDB_SONAME)
ln -s $(TDB_SOLIB) $(DESTDIR)$(libdir)/$(TDB_SONAME)
$(TDB_STLIB): $(TDB_OBJ)
ar -rv $(TDB_STLIB) $(TDB_OBJ)

View File

@ -26,6 +26,10 @@ installheaders:: installdirs
installlibs:: installdirs
cp tevent.pc $(DESTDIR)$(libdir)/pkgconfig
cp $(TEVENT_STLIB) $(TEVENT_SOLIB) $(DESTDIR)$(libdir)
rm -f $(DESTDIR)$(libdir)/$(TEVENT_SONAME)
ln -s $(TEVENT_SOLIB) $(DESTDIR)$(libdir)/$(TEVENT_SONAME)
rm -f $(DESTDIR)$(libdir)/$(TEVENT_SOBASE)
ln -s $(TEVENT_SOLIB) $(DESTDIR)$(libdir)/$(TEVENT_SOBASE)
install:: all installdirs installheaders installlibs $(PYTHON_INSTALL_TARGET)

View File

@ -27,11 +27,6 @@
* @brief time handling functions
*/
#ifndef TIME_T_MIN
/* we use 0 here, because (time_t)-1 means error */
#define TIME_T_MIN 0
#endif
#if (SIZEOF_LONG == 8)
#define TIME_FIXUP_CONSTANT_INT 11644473600L
#elif (SIZEOF_LONG_LONG == 8)
@ -40,15 +35,6 @@
/*
* we use the INT32_MAX here as on 64 bit systems,
* gmtime() fails with INT64_MAX
*/
#ifndef TIME_T_MAX
#define TIME_T_MAX MIN(INT32_MAX,_TYPE_MAXIMUM(time_t))
#endif
/**
External access to time_t_min and time_t_max.
**/

View File

@ -23,6 +23,20 @@
#define _PUBLIC_
#endif
#ifndef TIME_T_MIN
/* we use 0 here, because (time_t)-1 means error */
#define TIME_T_MIN 0
#endif
/*
* we use the INT32_MAX here as on 64 bit systems,
* gmtime() fails with INT64_MAX
*/
#ifndef TIME_T_MAX
#define TIME_T_MAX MIN(INT32_MAX,_TYPE_MAXIMUM(time_t))
#endif
/* 64 bit time (100 nanosec) 1601 - cifs6.txt, section 3.5, page 30, 4 byte aligned */
typedef uint64_t NTTIME;

View File

@ -120,6 +120,7 @@ fi
m4_include(../lib/socket_wrapper/config.m4)
m4_include(../lib/nss_wrapper/config.m4)
m4_include(../lib/util/time.m4)
m4_include(m4/swat.m4)
@ -2216,15 +2217,6 @@ if test x"$samba_cv_HAVE_FUNCTION_MACRO" = x"yes"; then
AC_DEFINE(HAVE_FUNCTION_MACRO,1,[Whether there is a __FUNCTION__ macro])
fi
AC_CACHE_CHECK([if gettimeofday takes tz argument],samba_cv_HAVE_GETTIMEOFDAY_TZ,[
AC_TRY_LINK([
#include <sys/time.h>
#include <unistd.h>], [struct timeval tv; return gettimeofday(&tv, NULL);],
samba_cv_HAVE_GETTIMEOFDAY_TZ=yes,
samba_cv_HAVE_GETTIMEOFDAY_TZ=no)])
if test x"$samba_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday takes a tz argument])
fi
if test x"$samba_cv_WITH_PROFILE" = x"yes"; then

View File

@ -1059,14 +1059,12 @@ void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unix
time_t cli_make_unix_date(struct cli_state *cli, const void *date_ptr);
time_t cli_make_unix_date2(struct cli_state *cli, const void *date_ptr);
time_t cli_make_unix_date3(struct cli_state *cli, const void *date_ptr);
bool nt_time_equals(const NTTIME *nt1, const NTTIME *nt2);
void TimeInit(void);
void get_process_uptime(struct timeval *ret_time);
time_t nt_time_to_unix_abs(const NTTIME *nt);
time_t uint64s_nt_time_to_unix_abs(const uint64_t *src);
void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts);
void unix_to_nt_time_abs(NTTIME *nt, time_t t);
bool null_mtime(time_t mtime);
const char *time_to_asc(const time_t t);
const char *display_time(NTTIME nttime);
bool nt_time_is_set(const NTTIME *nt);
@ -5396,6 +5394,7 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli,
const struct ndr_syntax_id *abstract_syntax,
struct rpc_cli_transport **presult);
struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p);
void rpccli_close_np_fd(struct rpc_pipe_client *p);
/* The following definitions come from rpc_client/rpc_transport_smbd.c */
@ -5426,11 +5425,15 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
struct rpc_cli_smbd_conn *conn,
const struct ndr_syntax_id *abstract_syntax,
struct rpc_cli_transport **presult);
struct cli_state *rpc_pipe_smbd_smb_conn(struct rpc_pipe_client *p);
/* The following definitions come from rpc_client/rpc_transport_sock.c */
NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd,
struct rpc_cli_transport **presult);
int rpccli_set_sock_timeout(struct rpc_pipe_client *rpccli, int timeout);
void rpccli_close_sock_fd(struct rpc_pipe_client *rpccli);
bool rpc_pipe_tcp_connection_ok(struct rpc_pipe_client *rpccli);
/* The following definitions come from rpc_client/cli_samr.c */

View File

@ -28,14 +28,6 @@
*/
#ifndef TIME_T_MIN
#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
: ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
#endif
#ifndef TIME_T_MAX
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
#endif
#define NTTIME_INFINITY (NTTIME)0x8000000000000000LL
#if (SIZEOF_LONG == 8)
@ -44,53 +36,6 @@
#define TIME_FIXUP_CONSTANT_INT 11644473600LL
#endif
/*******************************************************************
create a 16 bit dos packed date
********************************************************************/
static uint16_t make_dos_date1(struct tm *t)
{
uint16_t ret=0;
ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
return ret;
}
/*******************************************************************
create a 16 bit dos packed time
********************************************************************/
static uint16_t make_dos_time1(struct tm *t)
{
uint16_t ret=0;
ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
return ret;
}
/*******************************************************************
create a 32 bit dos packed date/time from some parameters
This takes a GMT time and returns a packed localtime structure
********************************************************************/
static uint32_t make_dos_date(time_t unixdate, int zone_offset)
{
struct tm *t;
uint32_t ret=0;
if (unixdate == 0) {
return 0;
}
unixdate -= zone_offset;
t = gmtime(&unixdate);
if (!t) {
return 0xFFFFFFFF;
}
ret = make_dos_date1(t);
ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
return ret;
}
/**
parse a nttime as a large integer in a string and return a NTTIME
@ -245,42 +190,6 @@ char *current_timestring(TALLOC_CTX *ctx, bool hires)
return timeval_string(ctx, &tv, hires);
}
/*******************************************************************
Put a dos date into a buffer (time/date format).
This takes GMT time and puts local time in the buffer.
********************************************************************/
static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset)
{
uint32_t x = make_dos_date(unixdate, zone_offset);
SIVAL(buf,offset,x);
}
/*******************************************************************
Put a dos date into a buffer (date/time format).
This takes GMT time and puts local time in the buffer.
********************************************************************/
static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset)
{
uint32_t x = make_dos_date(unixdate, zone_offset);
x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
SIVAL(buf,offset,x);
}
/*******************************************************************
Put a dos 32 bit "unix like" date into a buffer. This routine takes
GMT and converts it to LOCAL time before putting it (most SMBs assume
localtime for this sort of date)
********************************************************************/
static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
{
if (!null_mtime(unixdate)) {
unixdate -= zone_offset;
}
SIVAL(buf,offset,unixdate);
}
/***************************************************************************
@ -289,17 +198,17 @@ static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
void srv_put_dos_date(char *buf,int offset,time_t unixdate)
{
put_dos_date(buf, offset, unixdate, server_zone_offset);
push_dos_date(buf, offset, unixdate, server_zone_offset);
}
void srv_put_dos_date2(char *buf,int offset, time_t unixdate)
{
put_dos_date2(buf, offset, unixdate, server_zone_offset);
push_dos_date2(buf, offset, unixdate, server_zone_offset);
}
void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
{
put_dos_date3(buf, offset, unixdate, server_zone_offset);
push_dos_date3(buf, offset, unixdate, server_zone_offset);
}
void round_timespec(enum timestamp_set_resolution res, struct timespec *ts)
@ -396,7 +305,7 @@ time_t make_unix_date2(const void *date_ptr, int zone_offset)
time_t make_unix_date3(const void *date_ptr, int zone_offset)
{
time_t t = (time_t)IVAL(date_ptr,0);
if (!null_mtime(t)) {
if (!null_time(t)) {
t += zone_offset;
}
return(t);
@ -530,17 +439,17 @@ struct timespec interpret_long_date(const char *p)
void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate)
{
put_dos_date(buf, offset, unixdate, cli->serverzone);
push_dos_date(buf, offset, unixdate, cli->serverzone);
}
void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate)
{
put_dos_date2(buf, offset, unixdate, cli->serverzone);
push_dos_date2(buf, offset, unixdate, cli->serverzone);
}
void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate)
{
put_dos_date3(buf, offset, unixdate, cli->serverzone);
push_dos_date3(buf, offset, unixdate, cli->serverzone);
}
time_t cli_make_unix_date(struct cli_state *cli, const void *date_ptr)
@ -558,14 +467,6 @@ time_t cli_make_unix_date3(struct cli_state *cli, const void *date_ptr)
return make_unix_date3(date_ptr, cli->serverzone);
}
/****************************************************************************
Check if two NTTIMEs are the same.
****************************************************************************/
bool nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
{
return (*nt1 == *nt2);
}
/*******************************************************************
Re-read the smb serverzone value.
@ -746,17 +647,6 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
}
/****************************************************************************
Check if it's a null mtime.
****************************************************************************/
bool null_mtime(time_t mtime)
{
if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
return true;
return false;
}
/****************************************************************************
Utility function that always returns a const string even if localtime
and asctime fail.

File diff suppressed because it is too large Load Diff

View File

@ -88,6 +88,8 @@ static int commit_do(
#elif HAVE_FSYNC
result = fsync(fd);
#else
DEBUG(0, ("%s: WARNING: no commit support on this platform\n",
MODULE));
result = 0
#endif
if (result == 0) {

View File

@ -3035,12 +3035,30 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
unsigned int timeout)
{
struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli);
struct cli_state *cli;
if (cli == NULL) {
return 0;
if (rpc_cli->transport->transport == NCACN_NP) {
cli = rpc_pipe_np_smb_conn(rpc_cli);
if (cli == NULL) {
return 0;
}
return cli_set_timeout(cli, timeout);
}
return cli_set_timeout(cli, timeout);
if (rpc_cli->transport->transport == NCACN_IP_TCP ||
rpc_cli->transport->transport == NCALRPC) {
return rpccli_set_sock_timeout(rpc_cli, timeout);
}
if (rpc_cli->transport->transport == NCACN_INTERNAL) {
cli = rpc_pipe_smbd_smb_conn(rpc_cli);
if (!cli) {
return 0;
}
return cli_set_timeout(cli, timeout);
}
return 0;
}
bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])

View File

@ -182,6 +182,21 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli,
}
status = cli_do_rpc_ndr_recv(req, mem_ctx);
/*
* NT_STATUS_IO_TIMEOUT indicates network problem,
* tear the connection apart.
*/
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
if (cli->transport->transport == NCACN_IP_TCP ||
cli->transport->transport == NCALRPC) {
rpccli_close_sock_fd(cli);
}
if (cli->transport->transport == NCACN_NP) {
rpccli_close_np_fd(cli);
}
}
fail:
TALLOC_FREE(frame);
return status;

View File

@ -402,3 +402,15 @@ struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p)
}
return state->cli;
}
void rpccli_close_np_fd(struct rpc_pipe_client *p)
{
struct cli_state *cli = rpc_pipe_np_smb_conn(p);
if (cli) {
if (cli->fd != -1) {
close(cli->fd);
cli->fd = -1;
}
}
return;
}

View File

@ -682,3 +682,13 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
TALLOC_FREE(frame);
return status;
}
struct cli_state *rpc_pipe_smbd_smb_conn(struct rpc_pipe_client *p)
{
struct rpc_transport_smbd_state *state = talloc_get_type(p->transport->priv,
struct rpc_transport_smbd_state);
if (!state || !state->conn) {
return NULL;
}
return state->conn->cli;
}

View File

@ -24,6 +24,7 @@
struct rpc_transport_sock_state {
int fd;
int timeout;
};
static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *s)
@ -51,6 +52,7 @@ static struct tevent_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx,
priv, struct rpc_transport_sock_state);
struct tevent_req *req, *subreq;
struct rpc_sock_read_state *state;
struct timeval endtime;
req = tevent_req_create(mem_ctx, &state, struct rpc_sock_read_state);
if (req == NULL) {
@ -61,10 +63,16 @@ static struct tevent_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
state->transp = sock_transp;
endtime = timeval_current_ofs(0, sock_transp->timeout * 1000);
subreq = async_recv_send(state, ev, sock_transp->fd, data, size, 0);
if (subreq == NULL) {
goto fail;
}
if (!tevent_req_set_endtime(subreq, ev, endtime)) {
goto fail;
}
tevent_req_set_callback(subreq, rpc_sock_read_done, req);
return req;
fail:
@ -121,6 +129,7 @@ static struct tevent_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx,
priv, struct rpc_transport_sock_state);
struct tevent_req *req, *subreq;
struct rpc_sock_write_state *state;
struct timeval endtime;
req = tevent_req_create(mem_ctx, &state, struct rpc_sock_write_state);
if (req == NULL) {
@ -131,10 +140,16 @@ static struct tevent_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
state->transp = sock_transp;
endtime = timeval_current_ofs(0, sock_transp->timeout * 1000);
subreq = async_send_send(state, ev, sock_transp->fd, data, size, 0);
if (subreq == NULL) {
goto fail;
}
if (!tevent_req_set_endtime(subreq, ev, endtime)) {
goto fail;
}
tevent_req_set_callback(subreq, rpc_sock_write_done, req);
return req;
fail:
@ -193,6 +208,7 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd,
result->priv = state;
state->fd = fd;
state->timeout = 10000; /* 10 seconds. */
talloc_set_destructor(state, rpc_transport_sock_state_destructor);
result->trans_send = NULL;
@ -205,3 +221,40 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd,
*presult = result;
return NT_STATUS_OK;
}
int rpccli_set_sock_timeout(struct rpc_pipe_client *cli, int timeout)
{
struct rpc_transport_sock_state *state = talloc_get_type(cli->transport->priv,
struct rpc_transport_sock_state);
int orig_timeout;
if (!state) {
return 0;
}
orig_timeout = state->timeout;
state->timeout = timeout;
return orig_timeout;
}
void rpccli_close_sock_fd(struct rpc_pipe_client *cli)
{
struct rpc_transport_sock_state *state = talloc_get_type(cli->transport->priv,
struct rpc_transport_sock_state);
if (state) {
if (state->fd != -1) {
close(state->fd);
state->fd = -1;
}
}
return;
}
bool rpc_pipe_tcp_connection_ok(struct rpc_pipe_client *cli)
{
struct rpc_transport_sock_state *state = talloc_get_type(cli->transport->priv,
struct rpc_transport_sock_state);
if (state && state->fd != -1) {
return true;
}
return false;
}

View File

@ -903,6 +903,13 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, size_
out:
(*is_data_outstanding) = prs_offset(&p->out_data.frag) > n;
if (p->out_data.current_pdu_sent == prs_offset(&p->out_data.frag)) {
/* We've returned everything in the out_data.frag
* so we're done with this pdu. Free it and reset
* current_pdu_sent. */
p->out_data.current_pdu_sent = 0;
prs_mem_free(&p->out_data.frag);
}
return data_returned;
}

View File

@ -353,6 +353,11 @@ static void pipe_write_andx_done(struct tevent_req *subreq)
done:
chain_reply(req);
/*
* We must free here as the ownership of req was
* moved to the connection struct in reply_pipe_write_and_X().
*/
TALLOC_FREE(req);
}
/****************************************************************************
@ -458,4 +463,9 @@ static void pipe_read_andx_done(struct tevent_req *subreq)
done:
chain_reply(req);
/*
* We must free here as the ownership of req was
* moved to the connection struct in reply_pipe_read_and_X().
*/
TALLOC_FREE(req);
}

View File

@ -37,10 +37,10 @@ static int net_usage(struct net_context *c, int argc, const char **argv)
for (i=0; table[i].funcname != NULL; i++) {
if (c->display_usage) {
d_printf(_("net %s usage:\n"), table[i].funcname);
d_printf("\n%s\n\n", table[i].usage);
d_printf("\n%s\n\n", _(table[i].usage));
} else {
d_printf("%s %-15s %s\n", "net", table[i].funcname,
table[i].description);
_(table[i].description));
}
}

View File

@ -583,13 +583,13 @@ int net_run_function(struct net_context *c, int argc, const char **argv,
d_fprintf(stderr, _("Invalid command: %s %s\n"), whoami,
(argc > 0)?argv[0]:"");
}
d_printf("Usage:\n");
d_printf(_("Usage:\n"));
for (i=0; table[i].funcname != NULL; i++) {
if(c->display_usage == false)
d_printf("%s %-15s %s\n", whoami, table[i].funcname,
table[i].description);
_(table[i].description));
else
d_printf("%s\n", table[i].usage);
d_printf("%s\n", _(table[i].usage));
}
return c->display_usage?0:-1;
@ -599,7 +599,7 @@ void net_display_usage_from_functable(struct functable *table)
{
int i;
for (i=0; table[i].funcname != NULL; i++) {
d_printf("%s\n", table[i].usage);
d_printf("%s\n", _(table[i].usage));
}
}

View File

@ -1380,6 +1380,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
struct cache_entry *centry = NULL;
NTSTATUS status;
unsigned int i, retry;
bool old_status = domain->online;
if (!cache->tdb)
goto do_query;
@ -1388,6 +1389,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
if (!centry)
goto do_query;
do_fetch_cache:
*num_entries = centry_uint32(centry);
if (*num_entries == 0)
@ -1448,12 +1450,44 @@ do_query:
"connection cache\n"));
invalidate_cm_connection(&domain->conn);
}
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
/* store partial response. */
if (*num_entries > 0) {
/*
* humm, what about the status used for cache?
* Should it be NT_STATUS_OK?
*/
break;
}
/*
* domain is offline now, and there is no user entries,
* try to fetch from cache again.
*/
if (cache->tdb && !domain->online && !domain->internal && old_status) {
centry = wcache_fetch(cache, domain, "UL/%s", domain->name);
/* partial response... */
if (!centry) {
goto skip_save;
} else {
goto do_fetch_cache;
}
} else {
goto skip_save;
}
}
} while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) &&
(retry++ < 5));
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@ -1497,7 +1531,9 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
struct cache_entry *centry = NULL;
NTSTATUS status;
unsigned int i;
bool old_status;
old_status = domain->online;
if (!cache->tdb)
goto do_query;
@ -1505,6 +1541,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
if (!centry)
goto do_query;
do_fetch_cache:
*num_entries = centry_uint32(centry);
if (*num_entries == 0)
@ -1543,8 +1580,26 @@ do_query:
status = domain->backend->enum_dom_groups(domain, mem_ctx, num_entries, info);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (cache->tdb &&
!domain->online &&
!domain->internal &&
old_status) {
centry = wcache_fetch(cache, domain, "GL/%s/domain", domain->name);
if (centry) {
goto do_fetch_cache;
}
}
}
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@ -1571,7 +1626,9 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
struct cache_entry *centry = NULL;
NTSTATUS status;
unsigned int i;
bool old_status;
old_status = domain->online;
if (!cache->tdb)
goto do_query;
@ -1579,6 +1636,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
if (!centry)
goto do_query;
do_fetch_cache:
*num_entries = centry_uint32(centry);
if (*num_entries == 0)
@ -1627,8 +1685,26 @@ do_query:
status = domain->backend->enum_local_groups(domain, mem_ctx, num_entries, info);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (cache->tdb &&
!domain->internal &&
!domain->online &&
old_status) {
centry = wcache_fetch(cache, domain, "GL/%s/local", domain->name);
if (centry) {
goto do_fetch_cache;
}
}
}
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@ -1694,6 +1770,9 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
enum lsa_SidType *type)
{
NTSTATUS status;
bool old_status;
old_status = domain->online;
status = wcache_name_to_sid(domain, domain_name, name, sid, type);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@ -1719,6 +1798,19 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
status = domain->backend->name_to_sid(domain, mem_ctx, domain_name,
name, flags, sid, type);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (!domain->internal &&
!domain->online &&
old_status) {
NTSTATUS cache_status;
cache_status = wcache_name_to_sid(domain, domain_name, name, sid, type);
return cache_status;
}
}
/* and save it */
refresh_sequence_number(domain, false);
@ -1789,7 +1881,9 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
enum lsa_SidType *type)
{
NTSTATUS status;
bool old_status;
old_status = domain->online;
status = wcache_sid_to_name(domain, sid, mem_ctx, domain_name, name,
type);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@ -1815,8 +1909,25 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (!domain->internal &&
!domain->online &&
old_status) {
NTSTATUS cache_status;
cache_status = wcache_sid_to_name(domain, sid, mem_ctx,
domain_name, name, type);
return cache_status;
}
}
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type);
/* We can't save the name to sid mapping here, as with sid history a
@ -1839,7 +1950,9 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
bool have_mapped;
bool have_unmapped;
bool old_status;
old_status = domain->online;
*domain_name = NULL;
*names = NULL;
*types = NULL;
@ -1924,6 +2037,73 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
rids, num_rids, domain_name,
names, types);
if (NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (cache->tdb &&
!domain->internal &&
!domain->online &&
old_status) {
have_mapped = have_unmapped = false;
for (i=0; i<num_rids; i++) {
DOM_SID sid;
struct cache_entry *centry;
fstring tmp;
if (!sid_compose(&sid, domain_sid, rids[i])) {
result = NT_STATUS_INTERNAL_ERROR;
goto error;
}
centry = wcache_fetch(cache, domain, "SN/%s",
sid_to_fstring(tmp, &sid));
if (!centry) {
(*types)[i] = SID_NAME_UNKNOWN;
(*names)[i] = talloc_strdup(*names, "");
continue;
}
(*types)[i] = SID_NAME_UNKNOWN;
(*names)[i] = talloc_strdup(*names, "");
if (NT_STATUS_IS_OK(centry->status)) {
char *dom;
have_mapped = true;
(*types)[i] = (enum lsa_SidType)centry_uint32(centry);
dom = centry_string(centry, mem_ctx);
if (*domain_name == NULL) {
*domain_name = dom;
} else {
talloc_free(dom);
}
(*names)[i] = centry_string(centry, *names);
} else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)) {
have_unmapped = true;
} else {
/* something's definitely wrong */
result = centry->status;
goto error;
}
centry_free(centry);
}
if (!have_mapped) {
return NT_STATUS_NONE_MAPPED;
}
if (!have_unmapped) {
return NT_STATUS_OK;
}
return STATUS_SOME_UNMAPPED;
}
}
/*
None of the queried rids has been found so save all negative entries
*/
@ -2046,7 +2226,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
struct wbint_userinfo *info)
{
NTSTATUS status;
bool old_status;
old_status = domain->online;
status = wcache_query_user(domain, mem_ctx, user_sid, info);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
return status;
@ -2064,8 +2246,24 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
status = domain->backend->query_user(domain, mem_ctx, user_sid, info);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (!domain->internal &&
!domain->online &&
old_status) {
NTSTATUS cache_status;
cache_status = wcache_query_user(domain, mem_ctx, user_sid, info);
return cache_status;
}
}
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
wcache_save_user(domain, status, info);
return status;
@ -2140,7 +2338,9 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
NTSTATUS status;
unsigned int i;
fstring sid_string;
bool old_status;
old_status = domain->online;
status = wcache_lookup_usergroups(domain, mem_ctx, user_sid,
num_groups, user_gids);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@ -2160,11 +2360,28 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
status = domain->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (!domain->internal &&
!domain->online &&
old_status) {
NTSTATUS cache_status;
cache_status = wcache_lookup_usergroups(domain, mem_ctx, user_sid,
num_groups, user_gids);
return cache_status;
}
}
if ( NT_STATUS_EQUAL(status, NT_STATUS_SYNCHRONIZATION_REQUIRED) )
goto skip_save;
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@ -2272,7 +2489,9 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
NTSTATUS status;
char *sidlist;
int i;
bool old_status;
old_status = domain->online;
status = wcache_lookup_useraliases(domain, mem_ctx, num_sids, sids,
num_aliases, alias_rids);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@ -2297,8 +2516,25 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
num_sids, sids,
num_aliases, alias_rids);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (!domain->internal &&
!domain->online &&
old_status) {
NTSTATUS cache_status;
cache_status = wcache_lookup_useraliases(domain, mem_ctx, num_sids,
sids, num_aliases, alias_rids);
return cache_status;
}
}
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@ -2389,7 +2625,9 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
NTSTATUS status;
unsigned int i;
fstring sid_string;
bool old_status;
old_status = domain->online;
status = wcache_lookup_groupmem(domain, mem_ctx, group_sid, num_names,
sid_mem, names, name_types);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@ -2413,8 +2651,26 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
type, num_names,
sid_mem, names, name_types);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (!domain->internal &&
!domain->online &&
old_status) {
NTSTATUS cache_status;
cache_status = wcache_lookup_groupmem(domain, mem_ctx, group_sid,
num_names, sid_mem, names,
name_types);
return cache_status;
}
}
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@ -2449,7 +2705,71 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
struct netr_DomainTrustList *trusts)
{
NTSTATUS status;
struct winbind_cache *cache;
struct winbindd_tdc_domain *dom_list = NULL;
size_t num_domains = 0;
bool retval = false;
int i;
bool old_status;
old_status = domain->online;
trusts->count = 0;
trusts->array = NULL;
if (domain->online) {
goto do_query;
}
cache = get_cache(domain);
if (!cache || !cache->tdb) {
goto do_query;
}
retval = wcache_tdc_fetch_list(&dom_list, &num_domains);
if (!retval || !num_domains || !dom_list) {
TALLOC_FREE(dom_list);
goto do_query;
}
do_fetch_cache:
trusts->array = TALLOC_ZERO_ARRAY(mem_ctx, struct netr_DomainTrust, num_domains);
if (!trusts->array) {
TALLOC_FREE(dom_list);
return NT_STATUS_NO_MEMORY;
}
for (i = 0; i < num_domains; i++) {
struct netr_DomainTrust *trust;
struct dom_sid *sid;
struct winbindd_domain *dom;
dom = find_domain_from_name_noinit(dom_list[i].domain_name);
if (dom && dom->internal) {
continue;
}
trust = &trusts->array[trusts->count];
trust->netbios_name = talloc_strdup(trusts->array, dom_list[i].domain_name);
trust->dns_name = talloc_strdup(trusts->array, dom_list[i].dns_name);
sid = talloc(trusts->array, struct dom_sid);
if (!trust->netbios_name || !trust->dns_name ||
!sid) {
TALLOC_FREE(dom_list);
TALLOC_FREE(trusts->array);
return NT_STATUS_NO_MEMORY;
}
trust->trust_flags = dom_list[i].trust_flags;
trust->trust_attributes = dom_list[i].trust_attribs;
trust->trust_type = dom_list[i].trust_type;
sid_copy(sid, &dom_list[i].sid);
trust->sid = sid;
trusts->count++;
}
TALLOC_FREE(dom_list);
return NT_STATUS_OK;
do_query:
/* Return status value returned by seq number check */
if (!NT_STATUS_IS_OK(domain->last_status))
@ -2460,6 +2780,22 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
status = domain->backend->trusted_domains(domain, mem_ctx, trusts);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (!domain->internal &&
!domain->online &&
old_status) {
retval = wcache_tdc_fetch_list(&dom_list, &num_domains);
if (retval && num_domains && dom_list) {
TALLOC_FREE(trusts->array);
trusts->count = 0;
goto do_fetch_cache;
}
}
}
/* no trusts gives NT_STATUS_NO_MORE_ENTRIES resetting to NT_STATUS_OK
* so that the generic centry handling still applies correctly -
* Guenther*/
@ -2478,7 +2814,9 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain,
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
bool old_status;
old_status = domain->online;
if (!cache->tdb)
goto do_query;
@ -2487,6 +2825,7 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain,
if (!centry)
goto do_query;
do_fetch_cache:
policy->lockout_duration = centry_nttime(centry);
policy->lockout_window = centry_nttime(centry);
policy->lockout_threshold = centry_uint16(centry);
@ -2512,8 +2851,26 @@ do_query:
status = domain->backend->lockout_policy(domain, mem_ctx, policy);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (cache->tdb &&
!domain->internal &&
!domain->online &&
old_status) {
centry = wcache_fetch(cache, domain, "LOC_POL/%s", domain->name);
if (centry) {
goto do_fetch_cache;
}
}
}
/* and save it */
refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
wcache_save_lockout_policy(domain, status, policy);
return status;
@ -2527,7 +2884,9 @@ static NTSTATUS password_policy(struct winbindd_domain *domain,
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
bool old_status;
old_status = domain->online;
if (!cache->tdb)
goto do_query;
@ -2536,6 +2895,7 @@ static NTSTATUS password_policy(struct winbindd_domain *domain,
if (!centry)
goto do_query;
do_fetch_cache:
policy->min_password_length = centry_uint16(centry);
policy->password_history_length = centry_uint16(centry);
policy->password_properties = centry_uint32(centry);
@ -2563,11 +2923,27 @@ do_query:
status = domain->backend->password_policy(domain, mem_ctx, policy);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
if (cache->tdb &&
!domain->internal &&
!domain->online &&
old_status) {
centry = wcache_fetch(cache, domain, "PWD_POL/%s", domain->name);
if (centry) {
goto do_fetch_cache;
}
}
}
/* and save it */
refresh_sequence_number(domain, false);
if (NT_STATUS_IS_OK(status)) {
wcache_save_password_policy(domain, status, policy);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
wcache_save_password_policy(domain, status, policy);
return status;
}

View File

@ -2214,7 +2214,8 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
if (conn->lsa_pipe_tcp &&
conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP &&
conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY &&
rpc_pipe_tcp_connection_ok(conn->lsa_pipe_tcp)) {
goto done;
}

View File

@ -199,7 +199,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
talloc_destroy(mem_ctx2);
} while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
return NT_STATUS_OK;
return status;
}
/* List all domain groups */
@ -269,7 +269,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
return NT_STATUS_OK;
return result;
}
/* convert a single name to a sid in a domain */
@ -1286,12 +1286,8 @@ NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
* This call can take a long time
* allow the server to time out.
* 35 seconds should do it.
* NB
* only do this when the undelying transport is named pipe.
*/
if (cli->transport->transport == NCACN_NP) {
orig_timeout = rpccli_set_timeout(cli, 35000);
}
orig_timeout = rpccli_set_timeout(cli, 35000);
status = lookup_names_fn(cli,
mem_ctx,
@ -1304,9 +1300,7 @@ NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
types);
/* And restore our original timeout. */
if (cli->transport->transport == NCACN_NP) {
rpccli_set_timeout(cli, orig_timeout);
}
rpccli_set_timeout(cli, orig_timeout);
if (!NT_STATUS_IS_OK(status)) {
return status;

View File

@ -101,13 +101,14 @@ static void dreplsrv_op_notify_replica_sync_send(struct dreplsrv_op_notify_state
/*
called when we have an established connection
*/
static void dreplsrv_op_notify_connect_recv(struct composite_context *creq)
static void dreplsrv_op_notify_connect_done(struct tevent_req *subreq)
{
struct dreplsrv_op_notify_state *st = talloc_get_type(creq->async.private_data,
struct dreplsrv_op_notify_state);
struct dreplsrv_op_notify_state *st = tevent_req_callback_data(subreq,
struct dreplsrv_op_notify_state);
struct composite_context *c = st->creq;
c->status = dreplsrv_out_drsuapi_recv(creq);
c->status = dreplsrv_out_drsuapi_recv(subreq);
TALLOC_FREE(subreq);
if (!composite_is_ok(c)) return;
dreplsrv_op_notify_replica_sync_send(st);
@ -119,8 +120,8 @@ static void dreplsrv_op_notify_connect_recv(struct composite_context *creq)
static struct composite_context *dreplsrv_op_notify_send(struct dreplsrv_notify_operation *op)
{
struct composite_context *c;
struct composite_context *creq;
struct dreplsrv_op_notify_state *st;
struct tevent_req *subreq;
c = composite_create(op, op->service->task->event_ctx);
if (c == NULL) return NULL;
@ -131,8 +132,11 @@ static struct composite_context *dreplsrv_op_notify_send(struct dreplsrv_notify_
st->creq = c;
st->op = op;
creq = dreplsrv_out_drsuapi_send(op->source_dsa->conn);
composite_continue(c, creq, dreplsrv_op_notify_connect_recv, st);
subreq = dreplsrv_out_drsuapi_send(st,
op->service->task->event_ctx,
op->source_dsa->conn);
if (composite_nomem(subreq, c)) return c;
tevent_req_set_callback(subreq, dreplsrv_op_notify_connect_done, st);
return c;
}

View File

@ -34,10 +34,9 @@
#include "libcli/composite/composite.h"
#include "auth/gensec/gensec.h"
#include "param/param.h"
#include "../lib/util/tevent_ntstatus.h"
struct dreplsrv_out_drsuapi_state {
struct composite_context *creq;
struct dreplsrv_out_connection *conn;
struct dreplsrv_drsuapi_connection *drsuapi;
@ -46,139 +45,160 @@ struct dreplsrv_out_drsuapi_state {
struct drsuapi_DsBind bind_r;
};
static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq);
static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq);
struct composite_context *dreplsrv_out_drsuapi_send(struct dreplsrv_out_connection *conn)
struct tevent_req *dreplsrv_out_drsuapi_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct dreplsrv_out_connection *conn)
{
struct composite_context *c;
struct tevent_req *req;
struct dreplsrv_out_drsuapi_state *state;
struct composite_context *creq;
struct dreplsrv_out_drsuapi_state *st;
c = composite_create(conn, conn->service->task->event_ctx);
if (c == NULL) return NULL;
req = tevent_req_create(mem_ctx, &state,
struct dreplsrv_out_drsuapi_state);
if (req == NULL) {
return NULL;
}
st = talloc_zero(c, struct dreplsrv_out_drsuapi_state);
if (composite_nomem(st, c)) return c;
state->conn = conn;
state->drsuapi = conn->drsuapi;
c->private_data = st;
if (state->drsuapi && !state->drsuapi->pipe->conn->dead) {
tevent_req_done(req);
return tevent_req_post(req, ev);
}
st->creq = c;
st->conn = conn;
st->drsuapi = conn->drsuapi;
if (st->drsuapi && !st->drsuapi->pipe->conn->dead) {
composite_done(c);
return c;
} else if (st->drsuapi && st->drsuapi->pipe->conn->dead) {
talloc_free(st->drsuapi);
if (state->drsuapi && state->drsuapi->pipe->conn->dead) {
talloc_free(state->drsuapi);
conn->drsuapi = NULL;
}
st->drsuapi = talloc_zero(st, struct dreplsrv_drsuapi_connection);
if (composite_nomem(st->drsuapi, c)) return c;
state->drsuapi = talloc_zero(state, struct dreplsrv_drsuapi_connection);
if (tevent_req_nomem(state->drsuapi, req)) {
return tevent_req_post(req, ev);
}
creq = dcerpc_pipe_connect_b_send(st, conn->binding, &ndr_table_drsuapi,
creq = dcerpc_pipe_connect_b_send(state, conn->binding, &ndr_table_drsuapi,
conn->service->system_session_info->credentials,
c->event_ctx, conn->service->task->lp_ctx);
composite_continue(c, creq, dreplsrv_out_drsuapi_connect_recv, st);
ev, conn->service->task->lp_ctx);
if (tevent_req_nomem(creq, req)) {
return tevent_req_post(req, ev);
}
composite_continue(NULL, creq, dreplsrv_out_drsuapi_connect_done, req);
return c;
return req;
}
static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st);
static void dreplsrv_out_drsuapi_bind_done(struct rpc_request *rreq);
static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq)
static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq)
{
struct dreplsrv_out_drsuapi_state *st = talloc_get_type(creq->async.private_data,
struct dreplsrv_out_drsuapi_state);
struct composite_context *c = st->creq;
struct tevent_req *req = talloc_get_type(creq->async.private_data,
struct tevent_req);
struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
struct dreplsrv_out_drsuapi_state);
NTSTATUS status;
struct rpc_request *rreq;
c->status = dcerpc_pipe_connect_b_recv(creq, st->drsuapi, &st->drsuapi->pipe);
if (!composite_is_ok(c)) return;
c->status = gensec_session_key(st->drsuapi->pipe->conn->security_state.generic_state,
&st->drsuapi->gensec_skey);
if (!composite_is_ok(c)) return;
dreplsrv_out_drsuapi_bind_send(st);
}
static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req);
static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st)
{
struct composite_context *c = st->creq;
struct rpc_request *req;
st->bind_info_ctr.length = 28;
st->bind_info_ctr.info.info28 = st->conn->service->bind_info28;
st->bind_r.in.bind_guid = &st->conn->service->ntds_guid;
st->bind_r.in.bind_info = &st->bind_info_ctr;
st->bind_r.out.bind_handle = &st->drsuapi->bind_handle;
req = dcerpc_drsuapi_DsBind_send(st->drsuapi->pipe, st, &st->bind_r);
composite_continue_rpc(c, req, dreplsrv_out_drsuapi_bind_recv, st);
}
static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req)
{
struct dreplsrv_out_drsuapi_state *st = talloc_get_type(req->async.private_data,
struct dreplsrv_out_drsuapi_state);
struct composite_context *c = st->creq;
c->status = dcerpc_ndr_request_recv(req);
if (!composite_is_ok(c)) return;
if (!W_ERROR_IS_OK(st->bind_r.out.result)) {
composite_error(c, werror_to_ntstatus(st->bind_r.out.result));
status = dcerpc_pipe_connect_b_recv(creq,
state->drsuapi,
&state->drsuapi->pipe);
if (tevent_req_nterror(req, status)) {
return;
}
ZERO_STRUCT(st->drsuapi->remote_info28);
if (st->bind_r.out.bind_info) {
switch (st->bind_r.out.bind_info->length) {
status = gensec_session_key(state->drsuapi->pipe->conn->security_state.generic_state,
&state->drsuapi->gensec_skey);
if (tevent_req_nterror(req, status)) {
return;
}
state->bind_info_ctr.length = 28;
state->bind_info_ctr.info.info28 = state->conn->service->bind_info28;
state->bind_r.in.bind_guid = &state->conn->service->ntds_guid;
state->bind_r.in.bind_info = &state->bind_info_ctr;
state->bind_r.out.bind_handle = &state->drsuapi->bind_handle;
rreq = dcerpc_drsuapi_DsBind_send(state->drsuapi->pipe,
state,
&state->bind_r);
if (tevent_req_nomem(rreq, req)) {
return;
}
composite_continue_rpc(NULL, rreq, dreplsrv_out_drsuapi_bind_done, req);
}
static void dreplsrv_out_drsuapi_bind_done(struct rpc_request *rreq)
{
struct tevent_req *req = talloc_get_type(rreq->async.private_data,
struct tevent_req);
struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
struct dreplsrv_out_drsuapi_state);
NTSTATUS status;
status = dcerpc_ndr_request_recv(rreq);
if (tevent_req_nterror(req, status)) {
return;
}
if (!W_ERROR_IS_OK(state->bind_r.out.result)) {
status = werror_to_ntstatus(state->bind_r.out.result);
tevent_req_nterror(req, status);
return;
}
ZERO_STRUCT(state->drsuapi->remote_info28);
if (state->bind_r.out.bind_info) {
struct drsuapi_DsBindInfo28 *info28;
info28 = &state->drsuapi->remote_info28;
switch (state->bind_r.out.bind_info->length) {
case 24: {
struct drsuapi_DsBindInfo24 *info24;
info24 = &st->bind_r.out.bind_info->info.info24;
st->drsuapi->remote_info28.supported_extensions = info24->supported_extensions;
st->drsuapi->remote_info28.site_guid = info24->site_guid;
st->drsuapi->remote_info28.pid = info24->pid;
st->drsuapi->remote_info28.repl_epoch = 0;
info24 = &state->bind_r.out.bind_info->info.info24;
info28->supported_extensions = info24->supported_extensions;
info28->site_guid = info24->site_guid;
info28->pid = info24->pid;
info28->repl_epoch = 0;
break;
}
case 48: {
struct drsuapi_DsBindInfo48 *info48;
info48 = &st->bind_r.out.bind_info->info.info48;
st->drsuapi->remote_info28.supported_extensions = info48->supported_extensions;
st->drsuapi->remote_info28.site_guid = info48->site_guid;
st->drsuapi->remote_info28.pid = info48->pid;
st->drsuapi->remote_info28.repl_epoch = info48->repl_epoch;
info48 = &state->bind_r.out.bind_info->info.info48;
info28->supported_extensions = info48->supported_extensions;
info28->site_guid = info48->site_guid;
info28->pid = info48->pid;
info28->repl_epoch = info48->repl_epoch;
break;
}
case 28:
st->drsuapi->remote_info28 = st->bind_r.out.bind_info->info.info28;
*info28 = state->bind_r.out.bind_info->info.info28;
break;
}
}
composite_done(c);
tevent_req_done(req);
}
NTSTATUS dreplsrv_out_drsuapi_recv(struct composite_context *c)
NTSTATUS dreplsrv_out_drsuapi_recv(struct tevent_req *req)
{
struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
struct dreplsrv_out_drsuapi_state);
NTSTATUS status;
struct dreplsrv_out_drsuapi_state *st = talloc_get_type(c->private_data,
struct dreplsrv_out_drsuapi_state);
status = composite_wait(c);
if (NT_STATUS_IS_OK(status)) {
st->conn->drsuapi = talloc_steal(st->conn, st->drsuapi);
if (tevent_req_is_nterror(req, &status)) {
tevent_req_received(req);
return status;
}
talloc_free(c);
return status;
state->conn->drsuapi = talloc_move(state->conn, &state->drsuapi);
tevent_req_received(req);
return NT_STATUS_OK;
}
struct dreplsrv_op_pull_source_state {
@ -195,13 +215,13 @@ struct dreplsrv_op_pull_source_state {
struct drsuapi_DsGetNCChangesCtr6 *ctr6;
};
static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq);
static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq);
struct composite_context *dreplsrv_op_pull_source_send(struct dreplsrv_out_operation *op)
{
struct composite_context *c;
struct composite_context *creq;
struct dreplsrv_op_pull_source_state *st;
struct tevent_req *subreq;
c = composite_create(op, op->service->task->event_ctx);
if (c == NULL) return NULL;
@ -212,21 +232,25 @@ struct composite_context *dreplsrv_op_pull_source_send(struct dreplsrv_out_opera
st->creq = c;
st->op = op;
creq = dreplsrv_out_drsuapi_send(op->source_dsa->conn);
composite_continue(c, creq, dreplsrv_op_pull_source_connect_recv, st);
subreq = dreplsrv_out_drsuapi_send(st,
op->service->task->event_ctx,
op->source_dsa->conn);
if (composite_nomem(subreq, c)) return c;
tevent_req_set_callback(subreq, dreplsrv_op_pull_source_connect_done, st);
return c;
}
static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st);
static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq)
static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq)
{
struct dreplsrv_op_pull_source_state *st = talloc_get_type(creq->async.private_data,
struct dreplsrv_op_pull_source_state *st = tevent_req_callback_data(subreq,
struct dreplsrv_op_pull_source_state);
struct composite_context *c = st->creq;
c->status = dreplsrv_out_drsuapi_recv(creq);
c->status = dreplsrv_out_drsuapi_recv(subreq);
TALLOC_FREE(subreq);
if (!composite_is_ok(c)) return;
dreplsrv_op_pull_source_get_changes_send(st);

View File

@ -9,12 +9,12 @@
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/>.
*/
@ -333,37 +333,37 @@ static int samldb_check_samAccountName_callback(struct ldb_request *req,
{
struct samldb_ctx *ac;
int ret;
ac = talloc_get_type(req->context, struct samldb_ctx);
if (ares->error != LDB_SUCCESS) {
return ldb_module_done(ac->req, ares->controls,
ares->response, ares->error);
}
switch (ares->type) {
case LDB_REPLY_ENTRY:
case LDB_REPLY_ENTRY:
/* if we get an entry it means this samAccountName
* already exists */
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_ENTRY_ALREADY_EXISTS);
case LDB_REPLY_REFERRAL:
/* this should not happen */
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
case LDB_REPLY_DONE:
/* not found, go on */
talloc_free(ares);
ret = samldb_next_step(ac);
break;
}
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
}
return LDB_SUCCESS;
}
@ -374,16 +374,16 @@ static int samldb_check_samAccountName(struct samldb_ctx *ac)
const char *name;
char *filter;
int ret;
ldb = ldb_module_get_ctx(ac->module);
if (ldb_msg_find_element(ac->msg, "samAccountName") == NULL) {
ret = samldb_generate_samAccountName(ac->msg);
if (ret != LDB_SUCCESS) {
return ret;
}
}
name = ldb_msg_find_attr_as_string(ac->msg, "samAccountName", NULL);
if (name == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
@ -393,7 +393,7 @@ static int samldb_check_samAccountName(struct samldb_ctx *ac)
if (filter == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
ret = ldb_build_search_req(&req, ldb, ac,
ac->domain_dn, LDB_SCOPE_SUBTREE,
filter, NULL,
@ -569,7 +569,7 @@ static int samldb_get_sid_domain(struct samldb_ctx *ac)
/* get the domain component part of the provided SID */
ac->domain_sid->num_auths--;
filter = talloc_asprintf(ac,
filter = talloc_asprintf(ac,
"(&(objectSid=%s)"
"(|(objectClass=domain)"
"(objectClass=builtinDomain)))",
@ -713,7 +713,7 @@ static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
struct ldb_context *ldb;
ldb = ldb_module_get_ctx(ac->module);
ldb_asprintf_errstring(ldb,
"Failed to find group sid %s!",
"Failed to find group sid %s!",
dom_sid_string(ac->sid, ac->sid));
return LDB_ERR_UNWILLING_TO_PERFORM;
}
@ -918,36 +918,33 @@ done:
static int samldb_set_defaultObjectCategory(struct samldb_ctx *ac)
{
struct ldb_context *ldb;
struct ldb_message *msg;
struct ldb_request *req;
int ret;
if (ac->dn) {
struct ldb_request *req;
struct ldb_context *ldb;
struct ldb_message *msg = ldb_msg_new(ac);
msg->dn = ac->dn;
ldb = ldb_module_get_ctx(ac->module);
ldb_msg_add_empty(msg, "defaultObjectCategory", LDB_FLAG_MOD_REPLACE, NULL);
/* (Re)set the default object category to have it set to the DN in the
* storage format */
msg = ldb_msg_new(ac);
msg->dn = ac->msg->dn;
ldb_msg_add_empty(msg, "defaultObjectCategory",
LDB_FLAG_MOD_REPLACE, NULL);
ldb_msg_add_steal_string(msg, "defaultObjectCategory",
ldb_dn_alloc_linearized(msg, ac->dn));
ldb_msg_add_steal_string(msg, "defaultObjectCategory", ldb_dn_alloc_linearized(msg, ac->dn));
ldb = ldb_module_get_ctx(ac->module);
ret = ldb_build_mod_req(&req, ldb, ac,
msg, NULL,
ac, samldb_set_defaultObjectCategory_callback,
ac->req);
if (ret != LDB_SUCCESS) {
return ret;
}
return ldb_next_request(ac->module, req);
}
ret = samldb_next_step(ac);
ret = ldb_build_mod_req(&req, ldb, ac,
msg, NULL,
ac,
samldb_set_defaultObjectCategory_callback,
ac->req);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
talloc_free(msg);
return ret;
}
return ret;
return ldb_next_request(ac->module, req);
}
/*
@ -955,14 +952,35 @@ static int samldb_set_defaultObjectCategory(struct samldb_ctx *ac)
*/
static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *req,
struct ldb_reply *ares)
struct ldb_reply *ares)
{
struct ldb_context *ldb;
struct samldb_ctx *ac;
int ret;
ac = talloc_get_type(req->context, struct samldb_ctx);
ldb = ldb_module_get_ctx(ac->module);
if (!ares) {
ret = LDB_ERR_OPERATIONS_ERROR;
goto done;
}
if (ares->error != LDB_SUCCESS) {
if (ares->error == LDB_ERR_NO_SUCH_OBJECT) {
if (ldb_request_get_control(ac->req,
LDB_CONTROL_RELAX_OID) != NULL) {
/* Don't be pricky when the DN doesn't exist */
/* if we have the RELAX control specified */
ac->dn = req->op.search.base;
return samldb_next_step(ac);
} else {
ldb_set_errstring(ldb,
"samldb_find_defaultObjectCategory: "
"Invalid DN for 'defaultObjectCategory'!");
ares->error = LDB_ERR_CONSTRAINT_VIOLATION;
}
}
return ldb_module_done(ac->req, ares->controls,
ares->response, ares->error);
}
@ -970,22 +988,33 @@ static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *re
switch (ares->type) {
case LDB_REPLY_ENTRY:
ac->dn = talloc_steal(ac, ares->message->dn);
ret = LDB_SUCCESS;
break;
case LDB_REPLY_REFERRAL:
/* this should not happen */
return ldb_module_done(ac->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
talloc_free(ares);
ret = LDB_ERR_OPERATIONS_ERROR;
break;
case LDB_REPLY_DONE:
/* found or not found, go on */
talloc_free(ares);
ret = samldb_next_step(ac);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
if (ac->dn != NULL) {
/* when found go on */
ret = samldb_next_step(ac);
} else {
ret = LDB_ERR_OPERATIONS_ERROR;
}
break;
}
done:
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
}
return LDB_SUCCESS;
}
@ -993,40 +1022,57 @@ static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
{
struct ldb_context *ldb;
struct ldb_request *req;
int ret;
static const char *no_attrs[] = { NULL };
int ret;
const struct ldb_val *val;
struct ldb_dn *def_obj_cat_dn;
ldb = ldb_module_get_ctx(ac->module);
ac->dn = NULL;
if (ldb_msg_find_element(ac->msg, "defaultObjectCategory") == NULL) {
ret = ldb_build_search_req(&req, ldb, ac,
ac->msg->dn, LDB_SCOPE_BASE,
"objectClass=classSchema", no_attrs,
NULL,
ac, samldb_find_for_defaultObjectCategory_callback,
ac->req);
if (ret != LDB_SUCCESS) {
return ret;
val = ldb_msg_find_ldb_val(ac->msg, "defaultObjectCategory");
if (val != NULL) {
/* "defaultObjectCategory" has been set by the caller. Do some
* checks for consistency.
* NOTE: The real constraint check (that 'defaultObjectCategory'
* is the DN of the new objectclass or any parent of it) is
* still incomplete.
* For now we say that 'defaultObjectCategory' is valid if it
* exists and it is of objectclass "classSchema". */
def_obj_cat_dn = ldb_dn_from_ldb_val(ac, ldb, val);
if (def_obj_cat_dn == NULL) {
ldb_set_errstring(ldb,
"samldb_find_defaultObjectCategory: Invalid DN "
"for 'defaultObjectCategory'!");
return LDB_ERR_CONSTRAINT_VIOLATION;
}
ret = dsdb_request_add_controls(ac->module, req, DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT);
if (ret != LDB_SUCCESS) {
return ret;
}
return ldb_next_request(ac->module, req);
} else {
/* "defaultObjectCategory" has not been set by the caller. Use
* the entry DN for it. */
def_obj_cat_dn = ac->msg->dn;
}
ret = samldb_next_step(ac);
ret = ldb_build_search_req(&req, ldb, ac,
def_obj_cat_dn, LDB_SCOPE_BASE,
"objectClass=classSchema", no_attrs,
NULL,
ac, samldb_find_for_defaultObjectCategory_callback,
ac->req);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
return ret;
}
return ret;
ret = dsdb_request_add_controls(ac->module, req,
DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT);
if (ret != LDB_SUCCESS) {
return ret;
}
return ldb_next_request(ac->module, req);
}
/*
* samldb_add_entry (async)
*/
@ -1377,7 +1423,7 @@ static int samldb_foreign_notice_sid(struct samldb_ctx *ac)
}
filter = talloc_asprintf(ac,
filter = talloc_asprintf(ac,
"(&(objectSid=%s)"
"(|(objectClass=domain)"
"(objectClass=builtinDomain)))",

View File

@ -102,7 +102,7 @@ static int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_module *mo
"(objectClass=classSchema)");
if (ret != LDB_SUCCESS) {
ldb_asprintf_errstring(ldb,
"dsdb_schema: failed to search attributeSchema objects: %s",
"dsdb_schema: failed to search classSchema objects: %s",
ldb_errstring(ldb));
goto failed;
}

View File

@ -16,7 +16,7 @@ ldb_asq_OBJ_FILES = $(ldbsrcdir)/modules/asq.o
PRIVATE_DEPENDENCIES = LIBTALLOC LIBTEVENT
CFLAGS = -I$(ldbsrcdir)/include
INIT_FUNCTION = LDB_MODULE(sample)
SUBSYSTEM = LIBTESTLDB
SUBSYSTEM = LIBLDB
# End MODULE sample_module
################################################

View File

@ -132,9 +132,41 @@ systemOnly: FALSE
"""
self.ldb.add_ldif(ldif)
# Search for created attribute
res = []
res = self.ldb.search("cn=%s,%s" % (attr_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
self.assertEquals(len(res), 1)
self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_display_name)
self.assertTrue("schemaIDGUID" in res[0])
class_name = "test-Class" + time.strftime("%s", time.gmtime())
class_ldap_display_name = class_name.replace("-", "")
# First try to create a class with a wrong "defaultObjectCategory"
ldif = """
dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
objectClass: top
objectClass: classSchema
defaultObjectCategory: CN=_
adminDescription: """ + class_name + """
adminDisplayName: """ + class_name + """
cn: """ + class_name + """
governsId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
instanceType: 4
objectClassCategory: 1
subClassOf: organizationalPerson
systemFlags: 16
rDNAttID: cn
systemMustContain: cn
systemMustContain: """ + attr_ldap_display_name + """
systemOnly: FALSE
"""
try:
self.ldb.add_ldif(ldif)
self.fail()
except LdbError, (num, _):
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
ldif = """
dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
objectClass: top
@ -154,6 +186,14 @@ systemOnly: FALSE
"""
self.ldb.add_ldif(ldif)
# Search for created objectclass
res = []
res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
self.assertEquals(len(res), 1)
self.assertEquals(res[0]["lDAPDisplayName"][0], class_ldap_display_name)
self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0])
self.assertTrue("schemaIDGUID" in res[0])
ldif = """
dn:
changetype: modify
@ -179,21 +219,6 @@ name: """ + object_name + """
"""
self.ldb.add_ldif(ldif)
# Search for created attribute
res = []
res = self.ldb.search("cn=%s,%s" % (attr_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
self.assertEquals(len(res), 1)
self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_display_name)
self.assertTrue("schemaIDGUID" in res[0])
# Search for created objectclass
res = []
res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
self.assertEquals(len(res), 1)
self.assertEquals(res[0]["lDAPDisplayName"][0], class_ldap_display_name)
self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0])
self.assertTrue("schemaIDGUID" in res[0])
# Search for created object
res = []
res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["*"])

View File

@ -283,14 +283,19 @@ static void run_child_getaddrinfo(struct dns_ex_state *state, int fd)
hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
ret = getaddrinfo(state->name.name, "0", &hints, &res_list);
/* try to fallback in case of error */
if (state->do_fallback) {
switch (ret) {
#ifdef EAI_NODATA
if (ret == EAI_NODATA && state->do_fallback) {
#else
if (ret == EAI_NONAME && state->do_fallback) {
case EAI_NODATA:
#endif
/* getaddrinfo() doesn't handle CNAME records */
run_child_dns_lookup(state, fd);
return;
case EAI_NONAME:
/* getaddrinfo() doesn't handle CNAME records */
run_child_dns_lookup(state, fd);
return;
default:
break;
}
}
if (ret != 0) {
goto done;

View File

@ -643,10 +643,104 @@ static bool test_async(struct torture_context *tctx,
/* cleanup the second lock */
io.lockx.in.ulock_cnt = 1;
io.lockx.in.lock_cnt = 0;
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = &lock[1];
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);
/* If a lock request contained multiple ranges and we are cancelling
* one while it's still pending, what happens? */
torture_comment(tctx, "testing cancel 1/2 lock request\n");
/* Send request with two ranges */
io.lockx.in.timeout = -1;
io.lockx.in.ulock_cnt = 0;
io.lockx.in.lock_cnt = 2;
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = lock;
req = smb_raw_lock_send(cli->tree, &io);
torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
"Failed to setup pending lock (%s)\n", __location__));
/* Try to cancel the first lock range */
io.lockx.in.timeout = 0;
io.lockx.in.lock_cnt = 1;
io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = &lock[0];
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);
/* Locking request should've failed and second range should be
* unlocked */
status = smbcli_request_simple_recv(req);
CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
io.lockx.in.timeout = 0;
io.lockx.in.ulock_cnt = 0;
io.lockx.in.lock_cnt = 1;
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = &lock[1];
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);
/* Cleanup both locks */
io.lockx.in.ulock_cnt = 2;
io.lockx.in.lock_cnt = 0;
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = lock;
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);
torture_comment(tctx, "testing cancel 2/2 lock request\n");
/* Lock second range so it contends */
io.lockx.in.timeout = 0;
io.lockx.in.ulock_cnt = 0;
io.lockx.in.lock_cnt = 1;
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = &lock[1];
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);
/* Send request with two ranges */
io.lockx.in.timeout = -1;
io.lockx.in.ulock_cnt = 0;
io.lockx.in.lock_cnt = 2;
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = lock;
req = smb_raw_lock_send(cli->tree, &io);
torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
"Failed to setup pending lock (%s)\n", __location__));
/* Try to cancel the second lock range */
io.lockx.in.timeout = 0;
io.lockx.in.lock_cnt = 1;
io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = &lock[1];
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);
/* Locking request should've failed and first range should be
* unlocked */
status = smbcli_request_simple_recv(req);
CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
io.lockx.in.timeout = 0;
io.lockx.in.ulock_cnt = 0;
io.lockx.in.lock_cnt = 1;
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = &lock[0];
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);
/* Cleanup both locks */
io.lockx.in.ulock_cnt = 2;
io.lockx.in.lock_cnt = 0;
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.locks = lock;
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);
torture_comment(tctx, "testing cancel by unlock\n");
io.lockx.in.ulock_cnt = 0;
io.lockx.in.lock_cnt = 1;
@ -654,7 +748,7 @@ static bool test_async(struct torture_context *tctx,
io.lockx.in.timeout = 0;
io.lockx.in.locks = &lock[0];
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
CHECK_STATUS(status, NT_STATUS_OK);
io.lockx.in.timeout = 5000;
req = smb_raw_lock_send(cli->tree, &io);
@ -680,7 +774,7 @@ static bool test_async(struct torture_context *tctx,
io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
io.lockx.in.timeout = 0;
status = smb_raw_lock(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
t = time(NULL);
io.lockx.in.timeout = 10000;

View File

@ -5,7 +5,7 @@
Copyright (C) Tim Potter 2003
Copyright (C) Stefan Metzmacher 2005
Copyright (C) Jelmer Vernooij 2007
Copyright (C) Guenther Deschner 2009
Copyright (C) Guenther Deschner 2009-2010
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
@ -865,45 +865,67 @@ static bool test_GetPrinterDriver2(struct torture_context *tctx,
struct policy_handle *handle,
const char *driver_name);
static bool test_GetPrinter(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle)
static bool test_GetPrinter_level(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle,
uint32_t level,
union spoolss_PrinterInfo *info)
{
NTSTATUS status;
struct spoolss_GetPrinter r;
uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int i;
uint32_t needed;
r.in.handle = handle;
r.in.level = level;
r.in.buffer = NULL;
r.in.offered = 0;
r.out.needed = &needed;
torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
"GetPrinter failed");
if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
data_blob_clear(&blob);
r.in.buffer = &blob;
r.in.offered = needed;
torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
"GetPrinter failed");
}
torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
if (info && r.out.info) {
*info = *r.out.info;
}
return true;
}
static bool test_GetPrinter(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle)
{
uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int i;
for (i=0;i<ARRAY_SIZE(levels);i++) {
r.in.handle = handle;
r.in.level = levels[i];
r.in.buffer = NULL;
r.in.offered = 0;
r.out.needed = &needed;
torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
union spoolss_PrinterInfo info;
status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
ZERO_STRUCT(info);
if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
data_blob_clear(&blob);
r.in.buffer = &blob;
r.in.offered = needed;
status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
}
torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, levels[i], &info),
"failed to call GetPrinter");
torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
if ((r.in.level == 2) && r.out.info->info2.drivername && strlen(r.out.info->info2.drivername)) {
if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
torture_assert(tctx,
test_GetPrinterDriver2(tctx, p, handle, r.out.info->info2.drivername),
test_GetPrinterDriver2(tctx, p, handle, info.info2.drivername),
"failed to call test_GetPrinterDriver2");
}
}
@ -911,6 +933,32 @@ static bool test_GetPrinter(struct torture_context *tctx,
return true;
}
static bool test_SetPrinter(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle,
struct spoolss_SetPrinterInfoCtr *info_ctr,
struct spoolss_DevmodeContainer *devmode_ctr,
struct sec_desc_buf *secdesc_ctr,
enum spoolss_PrinterControl command)
{
struct spoolss_SetPrinter r;
r.in.handle = handle;
r.in.info_ctr = info_ctr;
r.in.devmode_ctr = devmode_ctr;
r.in.secdesc_ctr = secdesc_ctr;
r.in.command = command;
torture_comment(tctx, "Testing SetPrinter Level %d\n", r.in.info_ctr->level);
torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
"failed to call SetPrinter");
torture_assert_werr_ok(tctx, r.out.result,
"failed to call SetPrinter");
return true;
}
static bool test_SetPrinter_errors(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle)
@ -2618,6 +2666,181 @@ static bool test_SetPrinterDataEx(struct torture_context *tctx,
return true;
}
static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle,
uint32_t *change_id)
{
enum winreg_Type type;
union spoolss_PrinterData data;
torture_assert(tctx,
test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data),
"failed to call GetPrinterData");
torture_assert(tctx, type == REG_DWORD, "unexpected type");
*change_id = data.value;
return true;
}
static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle,
uint32_t *change_id)
{
enum winreg_Type type;
union spoolss_PrinterData data;
torture_assert(tctx,
test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data),
"failed to call GetPrinterData");
torture_assert(tctx, type == REG_DWORD, "unexpected type");
*change_id = data.value;
return true;
}
static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle,
uint32_t *change_id)
{
union spoolss_PrinterInfo info;
torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
"failed to query Printer level 0");
*change_id = info.info0.change_id;
return true;
}
static bool test_ChangeID(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct policy_handle *handle)
{
uint32_t change_id, change_id_ex, change_id_info;
uint32_t change_id2, change_id_ex2, change_id_info2;
union spoolss_PrinterInfo info;
const char *comment;
torture_comment(tctx, "Testing ChangeID: id change test #1\n");
torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
"failed to query for ChangeID");
torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
"failed to query for ChangeID");
torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
"failed to query for ChangeID");
torture_assert_int_equal(tctx, change_id, change_id_ex,
"change_ids should all be equal");
torture_assert_int_equal(tctx, change_id_ex, change_id_info,
"change_ids should all be equal");
torture_comment(tctx, "Testing ChangeID: id change test #2\n");
torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
"failed to query for ChangeID");
torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
"failed to query Printer level 2");
torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
"failed to query for ChangeID");
torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
"failed to query for ChangeID");
torture_assert_int_equal(tctx, change_id, change_id_ex,
"change_id should not have changed");
torture_assert_int_equal(tctx, change_id_ex, change_id_info,
"change_id should not have changed");
torture_comment(tctx, "Testing ChangeID: id change test #3\n");
torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
"failed to query for ChangeID");
torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
"failed to query for ChangeID");
torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
"failed to query for ChangeID");
torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
"failed to query Printer level 2");
comment = talloc_strdup(tctx, info.info2.comment);
{
struct spoolss_SetPrinterInfoCtr info_ctr;
struct spoolss_DevmodeContainer devmode_ctr;
struct sec_desc_buf secdesc_ctr;
struct spoolss_SetPrinterInfo2 info2;
ZERO_STRUCT(info_ctr);
ZERO_STRUCT(devmode_ctr);
ZERO_STRUCT(secdesc_ctr);
info2.servername = info.info2.servername;
info2.printername = info.info2.printername;
info2.sharename = info.info2.sharename;
info2.portname = info.info2.portname;
info2.drivername = info.info2.drivername;
info2.comment = "torture_comment";
info2.location = info.info2.location;
info2.devmode_ptr = 0;
info2.sepfile = info.info2.sepfile;
info2.printprocessor = info.info2.printprocessor;
info2.datatype = info.info2.datatype;
info2.parameters = info.info2.parameters;
info2.secdesc_ptr = 0;
info2.attributes = info.info2.attributes;
info2.priority = info.info2.priority;
info2.defaultpriority = info.info2.defaultpriority;
info2.starttime = info.info2.starttime;
info2.untiltime = info.info2.untiltime;
info2.status = info.info2.status;
info2.cjobs = info.info2.cjobs;
info2.averageppm = info.info2.averageppm;
info_ctr.level = 2;
info_ctr.info.info2 = &info2;
torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
"failed to call SetPrinter");
info2.comment = comment;
torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
"failed to call SetPrinter");
}
torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
"failed to query for ChangeID");
torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
"failed to query for ChangeID");
torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
"failed to query for ChangeID");
torture_assert_int_equal(tctx, change_id2, change_id_ex2,
"change_ids should all be equal");
torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
"change_ids should all be equal");
torture_assert(tctx, (change_id < change_id2),
talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
change_id2, change_id));
torture_assert(tctx, (change_id_ex < change_id_ex2),
talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
change_id_ex2, change_id_ex));
torture_assert(tctx, (change_id_info < change_id_info2),
talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
change_id_info2, change_id_info));
return true;
}
static bool test_SecondaryClosePrinter(struct torture_context *tctx,
struct dcerpc_pipe *p,
@ -2848,6 +3071,10 @@ static bool test_OpenPrinterEx(struct torture_context *tctx,
ret = false;
}
if (!test_ChangeID(tctx, p, &handle)) {
ret = false;
}
if (!torture_setting_bool(tctx, "samba3", false)) {
if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
ret = false;

View File

@ -52,16 +52,16 @@ testit "export keytab from domain (2nd time)" $VALGRIND $net export keytab $PREF
KRB5CCNAME="$PREFIX/tmpuserccache"
export KRB5CCNAME
testit "kinit with keytab as user" $samba4kinit --keytab=$PREFIX/tmpkeytab --request-pac nettestuser@$REALM || failed=`expr $failed + 1`
testit "kinit with keytab as user" $VALGRIND $samba4kinit --keytab=$PREFIX/tmpkeytab --request-pac nettestuser@$REALM || failed=`expr $failed + 1`
test_smbclient "Test login with user kerberos ccache" 'ls' -k yes || failed=`expr $failed + 1`
KRB5CCNAME="$PREFIX/tmpadminccache"
export KRB5CCNAME
testit "kinit with keytab as $USERNAME" $samba4kinit --keytab=$PREFIX/tmpkeytab --request-pac $USERNAME@$REALM || failed=`expr $failed + 1`
testit "kinit with keytab as $USERNAME" $VALGRIND $samba4kinit --keytab=$PREFIX/tmpkeytab --request-pac $USERNAME@$REALM || failed=`expr $failed + 1`
testit "del user" $VALGRIND $net user delete nettestuser -k yes $@ || failed=`expr $failed + 1`
rm -f tmpadminccache tmpuserccache tmpkeytab
rm -f $PREFIX/tmpadminccache $PREFIX/tmpuserccache $PREFIX/tmpkeytab
exit $failed