[PATCH] Cleanups and parallel idmap_script
Volker Lendecke
Volker.Lendecke at SerNet.DE
Tue Feb 23 14:14:34 UTC 2016
Hi!
Attached find a patchset that holds a few cleanups plus idmap_script
parallelized. Greatly boosts performance for many groups at login
time.
Review appreciated!
Thanks, Volker
--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 9b261b14760addb930c09dbe146d3590f7a7da7d Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 13 Jan 2016 11:15:36 +0100
Subject: [PATCH 01/12] py_xattr: Fix a "ignoring return value" warning
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source4/librpc/ndr/py_xattr.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/source4/librpc/ndr/py_xattr.c b/source4/librpc/ndr/py_xattr.c
index fcf2e66..4ebf135 100644
--- a/source4/librpc/ndr/py_xattr.c
+++ b/source4/librpc/ndr/py_xattr.c
@@ -43,12 +43,16 @@ static void ntacl_print_debug_helper(struct ndr_print *ndr, const char *format,
{
va_list ap;
char *s = NULL;
- int i;
+ int i, ret;
va_start(ap, format);
- vasprintf(&s, format, ap);
+ ret = vasprintf(&s, format, ap);
va_end(ap);
+ if (ret == -1) {
+ return;
+ }
+
for (i=0;i<ndr->depth;i++) {
printf(" ");
}
--
2.1.4
From 860a04fcc683fed0ebe3d73598cb36207eb3ec10 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 14 Jan 2016 11:51:39 +0100
Subject: [PATCH 02/12] smbd: Fix line length & whitespace in write_file
No code change intended. This file just looked to hard to read.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/smbd/fileio.c | 117 ++++++++++++++++++++++++++++++--------------------
1 file changed, 71 insertions(+), 46 deletions(-)
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 156c139..ec6333e 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -1,20 +1,20 @@
-/*
+/*
Unix SMB/Netbios implementation.
Version 1.9.
read/write to a files_struct
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Jeremy Allison 2000-2002. - write cache.
-
+
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/>.
*/
@@ -411,9 +411,9 @@ ssize_t write_file(struct smb_request *req,
wcp->file_size = pos + 1;
ret = SMB_VFS_FTRUNCATE(fsp, wcp->file_size);
if (ret == -1) {
- DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f"
- "error %s\n", fsp_str_dbg(fsp),
- (double)wcp->file_size, strerror(errno)));
+ DEBUG(0, ("wcp_file_size_change (%s): ftruncate of "
+ "size %.0f error %s\n", fsp_str_dbg(fsp),
+ (double)wcp->file_size, strerror(errno)));
return -1;
}
return 1;
@@ -428,8 +428,9 @@ ssize_t write_file(struct smb_request *req,
if (wcp->data_size) {
bool cache_flush_needed = False;
- if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) {
-
+ if ((pos >= wcp->offset) &&
+ (pos <= wcp->offset + wcp->data_size)) {
+
/* ASCII art.... JRA.
+--------------+-----
@@ -446,9 +447,13 @@ ssize_t write_file(struct smb_request *req,
* Start of write overlaps or abutts the existing data.
*/
- size_t data_used = MIN((wcp->alloc_size - (pos - wcp->offset)), n);
+ size_t data_used;
+
+ data_used = MIN((wcp->alloc_size - (pos - wcp->offset)),
+ n);
- memcpy(wcp->data + (pos - wcp->offset), data, data_used);
+ memcpy(wcp->data + (pos - wcp->offset), data,
+ data_used);
/*
* Update the current buffer size with the new data.
@@ -492,8 +497,9 @@ ssize_t write_file(struct smb_request *req,
write_path = 1;
- } else if ((pos < wcp->offset) && (pos + n > wcp->offset) &&
- (pos + n <= wcp->offset + wcp->alloc_size)) {
+ } else if ((pos < wcp->offset) &&
+ (pos + n > wcp->offset) &&
+ (pos + n <= wcp->offset + wcp->alloc_size)) {
/* ASCII art.... JRA.
@@ -551,10 +557,10 @@ ssize_t write_file(struct smb_request *req,
write_path = 2;
- } else if ( (pos >= wcp->file_size) &&
- (wcp->offset + wcp->data_size == wcp->file_size) &&
- (pos > wcp->offset + wcp->data_size) &&
- (pos < wcp->offset + wcp->alloc_size) ) {
+ } else if ((pos >= wcp->file_size) &&
+ (wcp->offset + wcp->data_size == wcp->file_size) &&
+ (pos > wcp->offset + wcp->data_size) &&
+ (pos < wcp->offset + wcp->alloc_size) ) {
/* ASCII art.... JRA.
@@ -582,7 +588,7 @@ ssize_t write_file(struct smb_request *req,
if(pos + n <= wcp->offset + wcp->alloc_size) {
data_used = n;
} else {
- data_used = wcp->offset + wcp->alloc_size - pos;
+ data_used = wcp->offset+wcp->alloc_size-pos;
}
/*
@@ -592,7 +598,8 @@ ssize_t write_file(struct smb_request *req,
memset(wcp->data + wcp->data_size, '\0',
pos - (wcp->offset + wcp->data_size) );
- memcpy(wcp->data + (pos - wcp->offset), data, data_used);
+ memcpy(wcp->data + (pos - wcp->offset), data,
+ data_used);
/*
* Update the current buffer size with the new data.
@@ -656,8 +663,9 @@ ssize_t write_file(struct smb_request *req,
| 1 Byte |
+--------+
- MS-Office seems to do this a lot to determine if there's enough
- space on the filesystem to write a new file.
+ MS-Office seems to do this a lot to determine if
+ there's enough space on the filesystem to write a new
+ file.
Change to :
@@ -695,9 +703,9 @@ ssize_t write_file(struct smb_request *req,
| Cached data | Cache buffer |
+---------------+---------------+
- +-------------------+
- | Data to write |
- +-------------------+
+ +---------------+
+ | Data to write |
+ +---------------+
Case 2).
@@ -722,35 +730,46 @@ ssize_t write_file(struct smb_request *req,
*/
/*
- * Write is bigger than buffer, or there is no overlap on the
- * low or high ends.
+ * Write is bigger than buffer, or there is no
+ * overlap on the low or high ends.
*/
- DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \
-len = %u\n",fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size ));
+ DEBUG(9,("write_file: non cacheable write : fd = %d, "
+ "pos = %.0f, len = %u, "
+ "current cache pos = %.0f len = %u\n",
+ fsp->fh->fd, (double)pos, (unsigned int)n,
+ (double)wcp->offset,
+ (unsigned int)wcp->data_size ));
/*
- * If write would fit in the cache, and is larger than
- * the data already in the cache, flush the cache and
- * preferentially copy the data new data into it. Otherwise
- * just write the data directly.
+ * If write would fit in the cache, and is
+ * larger than the data already in the cache,
+ * flush the cache and preferentially copy the
+ * data new data into it. Otherwise just write
+ * the data directly.
*/
if ( n <= wcp->alloc_size && n > wcp->data_size) {
cache_flush_needed = True;
} else {
- ssize_t ret = real_write_file(NULL,fsp, data, pos, n);
+ ssize_t ret = real_write_file(NULL, fsp, data,
+ pos, n);
/*
- * If the write overlaps the entire cache, then
- * discard the current contents of the cache.
- * Fix from Rasmus Borup Hansen rbh at math.ku.dk.
+ * If the write overlaps the entire
+ * cache, then discard the current
+ * contents of the cache. Fix from
+ * Rasmus Borup Hansen rbh at math.ku.dk.
*/
if ((pos <= wcp->offset) &&
- (pos + n >= wcp->offset + wcp->data_size) ) {
- DEBUG(9,("write_file: discarding overwritten write \
-cache: fd = %d, off=%.0f, size=%u\n", fsp->fh->fd, (double)wcp->offset, (unsigned int)wcp->data_size ));
+ (pos + n >= wcp->offset+wcp->data_size)) {
+ DEBUG(9,("write_file: discarding "
+ "overwritten write cache: "
+ "fd = %d, off=%.0f, "
+ "size=%u\n", fsp->fh->fd,
+ (double)wcp->offset,
+ (unsigned)wcp->data_size));
wcp->data_size = 0;
}
@@ -771,10 +790,14 @@ cache: fd = %d, off=%.0f, size=%u\n", fsp->fh->fd, (double)wcp->offset, (unsigne
}
if (cache_flush_needed) {
- DEBUG(3,("SAMBA_WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \
-n = %u, wcp->offset=%.0f, wcp->data_size=%u\n",
- write_path, fsp->fh->fd, (double)wcp->file_size, (double)pos, (unsigned int)n,
- (double)wcp->offset, (unsigned int)wcp->data_size ));
+ DEBUG(3, ("SAMBA_WRITE_FLUSH:%d: due to noncontinuous "
+ "write: fd = %d, size = %.0f, pos = %.0f, "
+ "n = %u, wcp->offset=%.0f, "
+ "wcp->data_size=%u\n",
+ write_path, fsp->fh->fd,
+ (double)wcp->file_size, (double)pos,
+ (unsigned int)n, (double)wcp->offset,
+ (unsigned int)wcp->data_size ));
flush_write_cache(fsp, SAMBA_WRITE_FLUSH);
}
@@ -845,13 +868,15 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n",
return -1;
}
}
- DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n",
- (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n));
+ DEBUG(9, ("wcp->offset = %.0f wcp->data_size = %u cache "
+ "return %u\n",
+ (double)wcp->offset, (unsigned int)wcp->data_size,
+ (unsigned int)n));
total_written += n;
return total_written; /* .... that's a write :) */
}
-
+
return total_written;
}
--
2.1.4
From 38f56ed0ebda3a1bd9fb1aa53b3a3e2ca4f61952 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 20 Feb 2016 10:07:11 +0100
Subject: [PATCH 03/12] lib: Move data_blob_list_item to source4
It's only used in dcesrv_call_state.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
lib/util/data_blob.h | 5 -----
source4/rpc_server/dcerpc_server.h | 5 +++++
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/util/data_blob.h b/lib/util/data_blob.h
index 94af767..799e953 100644
--- a/lib/util/data_blob.h
+++ b/lib/util/data_blob.h
@@ -40,11 +40,6 @@ typedef struct datablob {
size_t length;
} DATA_BLOB;
-struct data_blob_list_item {
- struct data_blob_list_item *prev,*next;
- DATA_BLOB blob;
-};
-
/* by making struct ldb_val and DATA_BLOB the same, we can simplify
a fair bit of code */
#define ldb_val datablob
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index 9a697ce..9f5cfab 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -76,6 +76,11 @@ enum dcesrv_call_list {
DCESRV_LIST_PENDING_CALL_LIST
};
+struct data_blob_list_item {
+ struct data_blob_list_item *prev,*next;
+ DATA_BLOB blob;
+};
+
/* the state of an ongoing dcerpc call */
struct dcesrv_call_state {
struct dcesrv_call_state *next, *prev;
--
2.1.4
From b8bc5ea030a58cfce440ac8926e4fc98101be6e8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Feb 2016 14:59:53 +0100
Subject: [PATCH 04/12] lib: Fix whitespace
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/lib/util_file.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index 5584d91..b11da71 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -2,17 +2,17 @@
* Unix SMB/CIFS implementation.
* SMB parameters and setup
* Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
- *
+ *
* 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/>.
*/
--
2.1.4
From 09b8a4ecc7387c28f87f062b715def100c252f4f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Feb 2016 15:46:06 +0100
Subject: [PATCH 05/12] lib: Remove sys_waitpid
We have waitpid in libreplace
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/include/proto.h | 1 -
source3/lib/server_prefork.c | 2 +-
source3/lib/smbrun.c | 4 ++--
source3/lib/system.c | 15 +--------------
source3/lib/tdb_validate.c | 2 +-
source3/printing/queue_process.c | 2 +-
source3/printing/spoolssd.c | 2 +-
source3/rpc_server/samr/srv_samr_chgpasswd.c | 2 +-
source3/smbd/server.c | 2 +-
source3/winbindd/winbindd.c | 2 +-
tests/fcntl_lock_thread.c | 5 -----
11 files changed, 10 insertions(+), 29 deletions(-)
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 09e9915..aaa5aee 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -243,7 +243,6 @@ int sys_fallocate(int fd, uint32_t mode, off_t offset, off_t len);
void kernel_flock(int fd, uint32_t share_mode, uint32_t access_mask);
DIR *sys_fdopendir(int fd);
int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev);
-int sys_waitpid(pid_t pid,int *status,int options);
char *sys_getwd(void);
void set_effective_capability(enum smbd_capability capability);
void drop_effective_capability(enum smbd_capability capability);
diff --git a/source3/lib/server_prefork.c b/source3/lib/server_prefork.c
index c725607..1d64db2 100644
--- a/source3/lib/server_prefork.c
+++ b/source3/lib/server_prefork.c
@@ -329,7 +329,7 @@ static void prefork_cleanup_loop(struct prefork_pool *pfp)
continue;
}
- pid = sys_waitpid(pfp->pool[i].pid, &status, WNOHANG);
+ pid = waitpid(pfp->pool[i].pid, &status, WNOHANG);
if (pid > 0) {
if (pfp->pool[i].status != PF_WORKER_EXITING) {
diff --git a/source3/lib/smbrun.c b/source3/lib/smbrun.c
index 55f7a87..63b0323 100644
--- a/source3/lib/smbrun.c
+++ b/source3/lib/smbrun.c
@@ -116,7 +116,7 @@ static int smbrun_internal(const char *cmd, int *outfd, bool sanitize)
/* the parent just waits for the child to exit */
- while((wpid = sys_waitpid(pid,&status,0)) < 0) {
+ while((wpid = waitpid(pid,&status,0)) < 0) {
if(errno == EINTR) {
errno = 0;
continue;
@@ -287,7 +287,7 @@ int smbrunsecret(const char *cmd, const char *secret)
close(ifd[1]);
/* the parent just waits for the child to exit */
- while((wpid = sys_waitpid(pid, &status, 0)) < 0) {
+ while((wpid = waitpid(pid, &status, 0)) < 0) {
if(errno == EINTR) {
errno = 0;
continue;
diff --git a/source3/lib/system.c b/source3/lib/system.c
index 0351e37..acc121d 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -572,19 +572,6 @@ int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
}
/*******************************************************************
-The wait() calls vary between systems
-********************************************************************/
-
-int sys_waitpid(pid_t pid,int *status,int options)
-{
-#ifdef HAVE_WAITPID
- return waitpid(pid,status,options);
-#else /* HAVE_WAITPID */
- return wait4(pid, status, options, NULL);
-#endif /* HAVE_WAITPID */
-}
-
-/*******************************************************************
System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
on error (malloc fail usually).
********************************************************************/
@@ -1200,7 +1187,7 @@ int sys_pclose(int fd)
*/
do {
- wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
+ wait_pid = waitpid (entry->child_pid, &wstatus, 0);
} while (wait_pid == -1 && errno == EINTR);
SAFE_FREE(entry);
diff --git a/source3/lib/tdb_validate.c b/source3/lib/tdb_validate.c
index 2592402..9db182f 100644
--- a/source3/lib/tdb_validate.c
+++ b/source3/lib/tdb_validate.c
@@ -135,7 +135,7 @@ int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn)
(unsigned int)child_pid));
DEBUG(10, ("tdb_validate: waiting for child to finish...\n"));
- while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) {
+ while ((wait_pid = waitpid(child_pid, &child_status, 0)) < 0) {
if (errno == EINTR) {
DEBUG(10, ("tdb_validate: got signal during waitpid, "
"retrying\n"));
diff --git a/source3/printing/queue_process.c b/source3/printing/queue_process.c
index 6e31ee4..c9e5522 100644
--- a/source3/printing/queue_process.c
+++ b/source3/printing/queue_process.c
@@ -269,7 +269,7 @@ static void bq_sig_chld_handler(struct tevent_context *ev_ctx,
int status;
pid_t pid;
- pid = sys_waitpid(-1, &status, WNOHANG);
+ pid = waitpid(-1, &status, WNOHANG);
if (WIFEXITED(status)) {
DEBUG(6, ("Bq child process %d terminated with %d\n",
(int)pid, WEXITSTATUS(status)));
diff --git a/source3/printing/spoolssd.c b/source3/printing/spoolssd.c
index 51d10b6..48a914e 100644
--- a/source3/printing/spoolssd.c
+++ b/source3/printing/spoolssd.c
@@ -478,7 +478,7 @@ static void check_updater_child(struct tevent_context *ev_ctx,
return;
}
- pid = sys_waitpid(background_lpq_updater_pid, &status, WNOHANG);
+ pid = waitpid(background_lpq_updater_pid, &status, WNOHANG);
if (pid > 0) {
DEBUG(2, ("The background queue child died... Restarting!\n"));
pid = start_background_queue(ev_ctx, msg_ctx, bq_logfile);
diff --git a/source3/rpc_server/samr/srv_samr_chgpasswd.c b/source3/rpc_server/samr/srv_samr_chgpasswd.c
index bfb7af6..ad4eaa7 100644
--- a/source3/rpc_server/samr/srv_samr_chgpasswd.c
+++ b/source3/rpc_server/samr/srv_samr_chgpasswd.c
@@ -430,7 +430,7 @@ static bool chat_with_program(char *passwordprogram, const struct passwd *pass,
kill(pid, SIGKILL); /* be sure to end this process */
}
- while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
+ while ((wpid = waitpid(pid, &wstat, 0)) < 0) {
if (errno == EINTR) {
errno = 0;
continue;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 42fcad6..d68615e 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -630,7 +630,7 @@ static void smbd_sig_chld_handler(struct tevent_context *ev,
talloc_get_type_abort(private_data,
struct smbd_parent_context);
- while ((pid = sys_waitpid(-1, &status, WNOHANG)) > 0) {
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
bool unclean_shutdown = False;
/* If the child terminated normally, assume
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index 78df632..002ba3f 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -432,7 +432,7 @@ static void winbindd_sig_chld_handler(struct tevent_context *ev,
{
pid_t pid;
- while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
+ while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
winbind_child_died(pid);
}
}
diff --git a/tests/fcntl_lock_thread.c b/tests/fcntl_lock_thread.c
index f311056..e341514 100644
--- a/tests/fcntl_lock_thread.c
+++ b/tests/fcntl_lock_thread.c
@@ -15,11 +15,6 @@
#include <errno.h>
#include <pthread.h>
-static int sys_waitpid(pid_t pid,int *status,int options)
-{
- return waitpid(pid,status,options);
-}
-
#define DATA "conftest.fcntl"
#define SEEK_SET 0
--
2.1.4
From 695ad1daad376dde6e4656b88dae9571795a7106 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Feb 2016 15:58:52 +0100
Subject: [PATCH 06/12] lib: Extract sys_popen()
This was added by Jeremy with 3cf31a194f5, do the (C) accordingly
sys_popen is a pretty isolated functionality, and I'd like to use it
soon without "includes.h", needed by "proto.h"
Except for one malloc->talloc this is supposed to be a 1:1 copy
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/include/proto.h | 2 -
source3/lib/sys_popen.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++
source3/lib/sys_popen.h | 26 +++++
source3/lib/system.c | 231 -------------------------------------------
source3/lib/util_file.c | 1 +
source3/wscript_build | 1 +
6 files changed, 281 insertions(+), 233 deletions(-)
create mode 100644 source3/lib/sys_popen.c
create mode 100644 source3/lib/sys_popen.h
diff --git a/source3/include/proto.h b/source3/include/proto.h
index aaa5aee..00ff9f2 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -251,8 +251,6 @@ void sys_srandom(unsigned int seed);
int groups_max(void);
int sys_getgroups(int setlen, gid_t *gidset);
int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset);
-int sys_popen(const char *command);
-int sys_pclose(int fd);
ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size);
ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size);
ssize_t sys_listxattr (const char *path, char *list, size_t size);
diff --git a/source3/lib/sys_popen.c b/source3/lib/sys_popen.c
new file mode 100644
index 0000000..8380789
--- /dev/null
+++ b/source3/lib/sys_popen.c
@@ -0,0 +1,253 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba system utilities
+ * Copyright (C) Jeremy Allison 2000
+ *
+ * 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 "replace.h"
+#include "system/wait.h"
+#include <talloc.h>
+#include "lib/sys_popen.h"
+#include "lib/util/debug.h"
+
+/**************************************************************************
+ Extract a command into an arg list.
+****************************************************************************/
+
+static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
+{
+ char *trunc_cmd;
+ char *saveptr;
+ char *ptr;
+ int argcl;
+ char **argl = NULL;
+ int i;
+
+ if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
+ DEBUG(0, ("talloc failed\n"));
+ goto nomem;
+ }
+
+ if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
+ TALLOC_FREE(trunc_cmd);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /*
+ * Count the args.
+ */
+
+ for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
+ argcl++;
+
+ TALLOC_FREE(trunc_cmd);
+
+ if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
+ goto nomem;
+ }
+
+ /*
+ * Now do the extraction.
+ */
+
+ if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
+ goto nomem;
+ }
+
+ ptr = strtok_r(trunc_cmd, " \t", &saveptr);
+ i = 0;
+
+ if (!(argl[i++] = talloc_strdup(argl, ptr))) {
+ goto nomem;
+ }
+
+ while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
+
+ if (!(argl[i++] = talloc_strdup(argl, ptr))) {
+ goto nomem;
+ }
+ }
+
+ argl[i++] = NULL;
+ TALLOC_FREE(trunc_cmd);
+ return argl;
+
+ nomem:
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(trunc_cmd);
+ TALLOC_FREE(argl);
+ errno = ENOMEM;
+ return NULL;
+}
+
+/**************************************************************************
+ Wrapper for popen. Safer as it doesn't search a path.
+ Modified from the glibc sources.
+ modified by tridge to return a file descriptor. We must kick our FILE* habit
+****************************************************************************/
+
+typedef struct _popen_list
+{
+ int fd;
+ pid_t child_pid;
+ struct _popen_list *next;
+} popen_list;
+
+static popen_list *popen_chain;
+
+int sys_popen(const char *command)
+{
+ int parent_end, child_end;
+ int pipe_fds[2];
+ popen_list *entry = NULL;
+ char **argl = NULL;
+ int ret;
+
+ if (!*command) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ret = pipe(pipe_fds);
+ if (ret < 0) {
+ DEBUG(0, ("sys_popen: error opening pipe: %s\n",
+ strerror(errno)));
+ return -1;
+ }
+
+ parent_end = pipe_fds[0];
+ child_end = pipe_fds[1];
+
+ entry = talloc_zero(NULL, popen_list);
+ if (entry == NULL) {
+ DEBUG(0, ("sys_popen: malloc failed\n"));
+ goto err_exit;
+ }
+
+ /*
+ * Extract the command and args into a NULL terminated array.
+ */
+
+ argl = extract_args(NULL, command);
+ if (argl == NULL) {
+ DEBUG(0, ("sys_popen: extract_args() failed: %s\n", strerror(errno)));
+ goto err_exit;
+ }
+
+ entry->child_pid = fork();
+
+ if (entry->child_pid == -1) {
+ DEBUG(0, ("sys_popen: fork failed: %s\n", strerror(errno)));
+ goto err_exit;
+ }
+
+ if (entry->child_pid == 0) {
+
+ /*
+ * Child !
+ */
+
+ int child_std_end = STDOUT_FILENO;
+ popen_list *p;
+
+ close(parent_end);
+ if (child_end != child_std_end) {
+ dup2 (child_end, child_std_end);
+ close (child_end);
+ }
+
+ /*
+ * POSIX.2: "popen() shall ensure that any streams from previous
+ * popen() calls that remain open in the parent process are closed
+ * in the new child process."
+ */
+
+ for (p = popen_chain; p; p = p->next)
+ close(p->fd);
+
+ ret = execv(argl[0], argl);
+ if (ret == -1) {
+ DEBUG(0, ("sys_popen: ERROR executing command "
+ "'%s': %s\n", command, strerror(errno)));
+ }
+ _exit (127);
+ }
+
+ /*
+ * Parent.
+ */
+
+ close (child_end);
+ TALLOC_FREE(argl);
+
+ /* Link into popen_chain. */
+ entry->next = popen_chain;
+ popen_chain = entry;
+ entry->fd = parent_end;
+
+ return entry->fd;
+
+err_exit:
+
+ TALLOC_FREE(entry);
+ TALLOC_FREE(argl);
+ close(pipe_fds[0]);
+ close(pipe_fds[1]);
+ return -1;
+}
+
+/**************************************************************************
+ Wrapper for pclose. Modified from the glibc sources.
+****************************************************************************/
+
+int sys_pclose(int fd)
+{
+ int wstatus;
+ popen_list **ptr = &popen_chain;
+ popen_list *entry = NULL;
+ pid_t wait_pid;
+ int status = -1;
+
+ /* Unlink from popen_chain. */
+ for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
+ if ((*ptr)->fd == fd) {
+ entry = *ptr;
+ *ptr = (*ptr)->next;
+ status = 0;
+ break;
+ }
+ }
+
+ if (status < 0 || close(entry->fd) < 0)
+ return -1;
+
+ /*
+ * As Samba is catching and eating child process
+ * exits we don't really care about the child exit
+ * code, a -1 with errno = ECHILD will do fine for us.
+ */
+
+ do {
+ wait_pid = waitpid (entry->child_pid, &wstatus, 0);
+ } while (wait_pid == -1 && errno == EINTR);
+
+ TALLOC_FREE(entry);
+
+ if (wait_pid == -1)
+ return -1;
+ return wstatus;
+}
diff --git a/source3/lib/sys_popen.h b/source3/lib/sys_popen.h
new file mode 100644
index 0000000..6807d3c
--- /dev/null
+++ b/source3/lib/sys_popen.h
@@ -0,0 +1,26 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba system utilities
+ * Copyright (C) Jeremy Allison 2000
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIB_SYS_POPEN_H__
+#define __LIB_SYS_POPEN_H__
+
+int sys_popen(const char *command);
+int sys_pclose(int fd);
+
+#endif
diff --git a/source3/lib/system.c b/source3/lib/system.c
index acc121d..3d3eeed 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -966,237 +966,6 @@ int sys_setgroups(gid_t UNUSED(primary_gid), int setlen, gid_t *gidset)
#endif
}
-/**************************************************************************
- Extract a command into an arg list.
-****************************************************************************/
-
-static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
-{
- char *trunc_cmd;
- char *saveptr;
- char *ptr;
- int argcl;
- char **argl = NULL;
- int i;
-
- if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
- DEBUG(0, ("talloc failed\n"));
- goto nomem;
- }
-
- if(!(ptr = strtok_r(trunc_cmd, " \t", &saveptr))) {
- TALLOC_FREE(trunc_cmd);
- errno = EINVAL;
- return NULL;
- }
-
- /*
- * Count the args.
- */
-
- for( argcl = 1; ptr; ptr = strtok_r(NULL, " \t", &saveptr))
- argcl++;
-
- TALLOC_FREE(trunc_cmd);
-
- if (!(argl = talloc_array(mem_ctx, char *, argcl + 1))) {
- goto nomem;
- }
-
- /*
- * Now do the extraction.
- */
-
- if (!(trunc_cmd = talloc_strdup(mem_ctx, command))) {
- goto nomem;
- }
-
- ptr = strtok_r(trunc_cmd, " \t", &saveptr);
- i = 0;
-
- if (!(argl[i++] = talloc_strdup(argl, ptr))) {
- goto nomem;
- }
-
- while((ptr = strtok_r(NULL, " \t", &saveptr)) != NULL) {
-
- if (!(argl[i++] = talloc_strdup(argl, ptr))) {
- goto nomem;
- }
- }
-
- argl[i++] = NULL;
- TALLOC_FREE(trunc_cmd);
- return argl;
-
- nomem:
- DEBUG(0, ("talloc failed\n"));
- TALLOC_FREE(trunc_cmd);
- TALLOC_FREE(argl);
- errno = ENOMEM;
- return NULL;
-}
-
-/**************************************************************************
- Wrapper for popen. Safer as it doesn't search a path.
- Modified from the glibc sources.
- modified by tridge to return a file descriptor. We must kick our FILE* habit
-****************************************************************************/
-
-typedef struct _popen_list
-{
- int fd;
- pid_t child_pid;
- struct _popen_list *next;
-} popen_list;
-
-static popen_list *popen_chain;
-
-int sys_popen(const char *command)
-{
- int parent_end, child_end;
- int pipe_fds[2];
- popen_list *entry = NULL;
- char **argl = NULL;
- int ret;
-
- if (!*command) {
- errno = EINVAL;
- return -1;
- }
-
- ret = pipe(pipe_fds);
- if (ret < 0) {
- DEBUG(0, ("sys_popen: error opening pipe: %s\n",
- strerror(errno)));
- return -1;
- }
-
- parent_end = pipe_fds[0];
- child_end = pipe_fds[1];
-
- entry = SMB_MALLOC_P(popen_list);
- if (entry == NULL) {
- DEBUG(0, ("sys_popen: malloc failed\n"));
- goto err_exit;
- }
-
- ZERO_STRUCTP(entry);
-
- /*
- * Extract the command and args into a NULL terminated array.
- */
-
- argl = extract_args(NULL, command);
- if (argl == NULL) {
- DEBUG(0, ("sys_popen: extract_args() failed: %s\n", strerror(errno)));
- goto err_exit;
- }
-
- entry->child_pid = fork();
-
- if (entry->child_pid == -1) {
- DEBUG(0, ("sys_popen: fork failed: %s\n", strerror(errno)));
- goto err_exit;
- }
-
- if (entry->child_pid == 0) {
-
- /*
- * Child !
- */
-
- int child_std_end = STDOUT_FILENO;
- popen_list *p;
-
- close(parent_end);
- if (child_end != child_std_end) {
- dup2 (child_end, child_std_end);
- close (child_end);
- }
-
- /*
- * POSIX.2: "popen() shall ensure that any streams from previous
- * popen() calls that remain open in the parent process are closed
- * in the new child process."
- */
-
- for (p = popen_chain; p; p = p->next)
- close(p->fd);
-
- ret = execv(argl[0], argl);
- if (ret == -1) {
- DEBUG(0, ("sys_popen: ERROR executing command "
- "'%s': %s\n", command, strerror(errno)));
- }
- _exit (127);
- }
-
- /*
- * Parent.
- */
-
- close (child_end);
- TALLOC_FREE(argl);
-
- /* Link into popen_chain. */
- entry->next = popen_chain;
- popen_chain = entry;
- entry->fd = parent_end;
-
- return entry->fd;
-
-err_exit:
-
- SAFE_FREE(entry);
- TALLOC_FREE(argl);
- close(pipe_fds[0]);
- close(pipe_fds[1]);
- return -1;
-}
-
-/**************************************************************************
- Wrapper for pclose. Modified from the glibc sources.
-****************************************************************************/
-
-int sys_pclose(int fd)
-{
- int wstatus;
- popen_list **ptr = &popen_chain;
- popen_list *entry = NULL;
- pid_t wait_pid;
- int status = -1;
-
- /* Unlink from popen_chain. */
- for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
- if ((*ptr)->fd == fd) {
- entry = *ptr;
- *ptr = (*ptr)->next;
- status = 0;
- break;
- }
- }
-
- if (status < 0 || close(entry->fd) < 0)
- return -1;
-
- /*
- * As Samba is catching and eating child process
- * exits we don't really care about the child exit
- * code, a -1 with errno = ECHILD will do fine for us.
- */
-
- do {
- wait_pid = waitpid (entry->child_pid, &wstatus, 0);
- } while (wait_pid == -1 && errno == EINTR);
-
- SAFE_FREE(entry);
-
- if (wait_pid == -1)
- return -1;
- return wstatus;
-}
-
/****************************************************************************
Return the major devicenumber for UNIX extensions.
****************************************************************************/
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index b11da71..533680b 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -19,6 +19,7 @@
#include "includes.h"
#include "lib/util/sys_rw.h"
+#include "lib/sys_popen.h"
/**
Load from a pipe into memory.
diff --git a/source3/wscript_build b/source3/wscript_build
index 9ec11f9..1a7e05e 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -261,6 +261,7 @@ bld.SAMBA3_SUBSYSTEM('samba3util',
lib/util_sock.c
lib/util_tsock.c
lib/util_transfer_file.c
+ lib/sys_popen.c
lib/sock_exec.c''',
deps='ndr LIBTSOCKET samba-security NDR_SECURITY samba-util util_tdb sys_rw iov_buf')
--
2.1.4
From 3b71c815df05d3feb37a47a7b7abc0a34a27f4a8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Feb 2016 16:24:29 +0100
Subject: [PATCH 07/12] lib: Remove an unimplemented prototype
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/include/proto.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 00ff9f2..244c32e 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -452,7 +452,6 @@ bool sid_check_is_wellknown_builtin(const struct dom_sid *sid);
/* The following definitions come from lib/util_file.c */
char **file_lines_pload(const char *syscmd, int *numlines);
-void file_lines_free(char **lines);
/* The following definitions come from lib/util_nscd.c */
--
2.1.4
From b016c62e5c99e8b2e1de452a8bd3a6b6aa96acfb Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Feb 2016 16:29:01 +0100
Subject: [PATCH 08/12] lib: Add "mem_ctx" to file_lines_pload
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/include/proto.h | 3 ++-
source3/lib/sysquotas.c | 4 ++--
source3/lib/util_file.c | 5 +++--
source3/printing/print_svid.c | 4 ++--
source3/smbd/dfree.c | 2 +-
source3/winbindd/idmap_script.c | 2 +-
6 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 244c32e..5fcea9d 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -451,7 +451,8 @@ bool sid_check_is_wellknown_builtin(const struct dom_sid *sid);
/* The following definitions come from lib/util_file.c */
-char **file_lines_pload(const char *syscmd, int *numlines);
+char **file_lines_pload(TALLOC_CTX *mem_ctx, const char *syscmd,
+ int *numlines);
/* The following definitions come from lib/util_nscd.c */
diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c
index bacc4b2..95051a5 100644
--- a/source3/lib/sysquotas.c
+++ b/source3/lib/sysquotas.c
@@ -268,7 +268,7 @@ static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
DEBUG (3, ("get_quota: Running command %s\n", syscmd));
- lines = file_lines_pload(syscmd, NULL);
+ lines = file_lines_pload(talloc_tos(), syscmd, NULL);
SAFE_FREE(syscmd);
if (lines) {
@@ -416,7 +416,7 @@ static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
DEBUG (3, ("get_quota: Running command %s\n", syscmd));
- lines = file_lines_pload(syscmd, NULL);
+ lines = file_lines_pload(talloc_tos(), syscmd, NULL);
SAFE_FREE(syscmd);
if (lines) {
char *line = lines[0];
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index 533680b..3016c9b 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -74,7 +74,8 @@ static char *file_pload(const char *syscmd, size_t *size)
must be freed with TALLOC_FREE.
**/
-char **file_lines_pload(const char *syscmd, int *numlines)
+char **file_lines_pload(TALLOC_CTX *mem_ctx, const char *syscmd,
+ int *numlines)
{
char *p;
size_t size;
@@ -84,5 +85,5 @@ char **file_lines_pload(const char *syscmd, int *numlines)
return NULL;
}
- return file_lines_parse(p, size, numlines, NULL);
+ return file_lines_parse(p, size, numlines, mem_ctx);
}
diff --git a/source3/printing/print_svid.c b/source3/printing/print_svid.c
index 879661b..3b95539 100644
--- a/source3/printing/print_svid.c
+++ b/source3/printing/print_svid.c
@@ -47,8 +47,8 @@ bool sysv_cache_reload(struct pcap_cache **_pcache)
DEBUG(5, ("reloading sysv printcap cache\n"));
#endif
- if ((lines = file_lines_pload("/usr/bin/lpstat -v", NULL)) == NULL)
- {
+ lines = file_lines_pload(talloc_tos(), "/usr/bin/lpstat -v", NULL);
+ if (lines == NULL) {
#if defined(HPUX)
/*
diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
index 765fbe6..188faa2 100644
--- a/source3/smbd/dfree.c
+++ b/source3/smbd/dfree.c
@@ -83,7 +83,7 @@ uint64_t sys_disk_free(connection_struct *conn, const char *path,
DEBUG (3, ("disk_free: Running command '%s'\n", syscmd));
- lines = file_lines_pload(syscmd, NULL);
+ lines = file_lines_pload(talloc_tos(), syscmd, NULL);
if (lines != NULL) {
char *line = lines[0];
diff --git a/source3/winbindd/idmap_script.c b/source3/winbindd/idmap_script.c
index e758b4e..fbde6c5 100644
--- a/source3/winbindd/idmap_script.c
+++ b/source3/winbindd/idmap_script.c
@@ -81,7 +81,7 @@ static NTSTATUS idmap_script_script(struct idmap_script_context *ctx,
return NT_STATUS_NO_MEMORY;
}
- lines = file_lines_pload(cmd, &numlines);
+ lines = file_lines_pload(talloc_tos(), cmd, &numlines);
talloc_free(cmd);
if (!lines) {
return NT_STATUS_NONE_MAPPED;
--
2.1.4
From b438f4ac62d1c82a70af326ee16544e425c9533f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Feb 2016 17:01:04 +0100
Subject: [PATCH 09/12] lib: Add file_pload_send/recv
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/include/proto.h | 6 +++
source3/lib/util_file.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+)
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 5fcea9d..362a462 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -451,6 +451,12 @@ bool sid_check_is_wellknown_builtin(const struct dom_sid *sid);
/* The following definitions come from lib/util_file.c */
+struct tevent_req *file_pload_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *syscmd, size_t maxsize);
+int file_pload_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint8_t **buf);
+
char **file_lines_pload(TALLOC_CTX *mem_ctx, const char *syscmd,
int *numlines);
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index 3016c9b..e8e9b27 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -20,6 +20,133 @@
#include "includes.h"
#include "lib/util/sys_rw.h"
#include "lib/sys_popen.h"
+#include "lib/async_req/async_sock.h"
+#include "lib/util/tevent_unix.h"
+
+struct file_pload_state {
+ struct tevent_context *ev;
+ size_t maxsize;
+ int fd;
+ uint8_t *buf;
+};
+
+static int file_pload_state_destructor(struct file_pload_state *s);
+static void file_pload_readable(struct tevent_req *subreq);
+
+struct tevent_req *file_pload_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *syscmd, size_t maxsize)
+{
+ struct tevent_req *req, *subreq;
+ struct file_pload_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct file_pload_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->maxsize = maxsize;
+
+ state->fd = sys_popen(syscmd);
+ if (state->fd == -1) {
+ tevent_req_error(req, errno);
+ return tevent_req_post(req, ev);
+ }
+ talloc_set_destructor(state, file_pload_state_destructor);
+
+ subreq = wait_for_read_send(state, state->ev, state->fd, false);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, file_pload_readable, req);
+ return req;
+}
+
+static int file_pload_state_destructor(struct file_pload_state *s)
+{
+ if (s->fd != -1) {
+ sys_pclose(s->fd);
+ s->fd = -1;
+ }
+ return 0;
+}
+
+static void file_pload_readable(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct file_pload_state *state = tevent_req_data(
+ req, struct file_pload_state);
+ uint8_t buf[1024];
+ uint8_t *tmp;
+ ssize_t nread;
+ size_t bufsize;
+ int err;
+ bool ok;
+
+ ok = wait_for_read_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (!ok) {
+ tevent_req_error(req, err);
+ return;
+ }
+
+ nread = sys_read(state->fd, buf, sizeof(buf));
+ if (nread == -1) {
+ tevent_req_error(req, errno);
+ return;
+ }
+ if (nread == 0) {
+ tevent_req_done(req);
+ return;
+ }
+
+ bufsize = talloc_get_size(state->buf);
+
+ if (((bufsize + nread) < bufsize) ||
+ ((bufsize + nread + 1) < bufsize)) {
+ /* overflow */
+ tevent_req_error(req, EMSGSIZE);
+ return;
+ }
+
+ if ((state->maxsize != 0) && ((bufsize + nread) > state->maxsize)) {
+ tevent_req_error(req, EMSGSIZE);
+ return;
+ }
+
+ tmp = talloc_realloc(state, state->buf, uint8_t, bufsize + nread + 1);
+ if (tevent_req_nomem(tmp, req)) {
+ return;
+ }
+ state->buf = tmp;
+
+ memcpy(state->buf + bufsize, buf, nread);
+ state->buf[bufsize+nread] = '\0';
+
+ subreq = wait_for_read_send(state, state->ev, state->fd, false);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, file_pload_readable, req);
+}
+
+int file_pload_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint8_t **buf)
+{
+ struct file_pload_state *state = tevent_req_data(
+ req, struct file_pload_state);
+ int err;
+
+ if (tevent_req_is_unix_error(req, &err)) {
+ return err;
+ }
+ *buf = talloc_move(mem_ctx, &state->buf);
+
+ tevent_req_received(req);
+
+ return 0;
+}
/**
Load from a pipe into memory.
--
2.1.4
From db08acd1f1a76aa37e7e5099ed3676de8fd6f191 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 16 Feb 2016 17:09:43 +0100
Subject: [PATCH 10/12] lib: Remove "includes.h" from util_file.c
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/include/proto.h | 11 -----------
source3/lib/sysquotas.c | 1 +
source3/lib/util_file.c | 5 ++++-
source3/lib/util_file.h | 35 +++++++++++++++++++++++++++++++++++
source3/printing/print_svid.c | 1 +
source3/smbd/dfree.c | 1 +
source3/winbindd/idmap_script.c | 1 +
7 files changed, 43 insertions(+), 12 deletions(-)
create mode 100644 source3/lib/util_file.h
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 362a462..0c15f96 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -449,17 +449,6 @@ bool sid_check_is_builtin(const struct dom_sid *sid);
bool sid_check_is_in_builtin(const struct dom_sid *sid);
bool sid_check_is_wellknown_builtin(const struct dom_sid *sid);
-/* The following definitions come from lib/util_file.c */
-
-struct tevent_req *file_pload_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- const char *syscmd, size_t maxsize);
-int file_pload_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- uint8_t **buf);
-
-char **file_lines_pload(TALLOC_CTX *mem_ctx, const char *syscmd,
- int *numlines);
-
/* The following definitions come from lib/util_nscd.c */
void smb_nscd_flush_user_cache(void);
diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c
index 95051a5..102e458 100644
--- a/source3/lib/sysquotas.c
+++ b/source3/lib/sysquotas.c
@@ -19,6 +19,7 @@
#include "includes.h"
+#include "lib/util_file.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_QUOTA
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index e8e9b27..d3139e5 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -17,7 +17,10 @@
* this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "includes.h"
+#include "replace.h"
+#include "lib/util_file.h"
+#include "lib/util/debug.h"
+#include "lib/util/samba_util.h"
#include "lib/util/sys_rw.h"
#include "lib/sys_popen.h"
#include "lib/async_req/async_sock.h"
diff --git a/source3/lib/util_file.h b/source3/lib/util_file.h
new file mode 100644
index 0000000..9175ed0
--- /dev/null
+++ b/source3/lib/util_file.h
@@ -0,0 +1,35 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * SMB parameters and setup
+ * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIB_UTIL_FILE_H__
+#define __LIB_UTIL_FILE_H__
+
+#include "replace.h"
+#include <tevent.h>
+
+struct tevent_req *file_pload_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *syscmd, size_t maxsize);
+int file_pload_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint8_t **buf);
+
+char **file_lines_pload(TALLOC_CTX *mem_ctx, const char *syscmd,
+ int *numlines);
+
+#endif
diff --git a/source3/printing/print_svid.c b/source3/printing/print_svid.c
index 3b95539..f041ef4 100644
--- a/source3/printing/print_svid.c
+++ b/source3/printing/print_svid.c
@@ -33,6 +33,7 @@
#include "includes.h"
#include "printing/pcap.h"
+#include "lib/util_file.h"
#if defined(SYSV) || defined(HPUX)
bool sysv_cache_reload(struct pcap_cache **_pcache)
diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
index 188faa2..fc52e51 100644
--- a/source3/smbd/dfree.c
+++ b/source3/smbd/dfree.c
@@ -20,6 +20,7 @@
#include "includes.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
+#include "lib/util_file.h"
/****************************************************************************
Normalise for DOS usage.
diff --git a/source3/winbindd/idmap_script.c b/source3/winbindd/idmap_script.c
index fbde6c5..a929d6e 100644
--- a/source3/winbindd/idmap_script.c
+++ b/source3/winbindd/idmap_script.c
@@ -35,6 +35,7 @@
#include "idmap.h"
#include "idmap_rw.h"
#include "../libcli/security/dom_sid.h"
+#include "lib/util_file.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_IDMAP
--
2.1.4
From b9359c91a1176875d7d95e49b34343e83a7e97ad Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 22 Feb 2016 11:59:52 +0100
Subject: [PATCH 11/12] lib: Avoid an unnecessary cast
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/lib/g_lock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
index 30c5f52..346c1ed 100644
--- a/source3/lib/g_lock.c
+++ b/source3/lib/g_lock.c
@@ -99,7 +99,7 @@ static bool g_lock_parse(TALLOC_CTX *mem_ctx, TDB_DATA data,
struct g_lock_rec *locks;
if ((data.dsize % sizeof(struct g_lock_rec)) != 0) {
- DEBUG(1, ("invalid lock record length %d\n", (int)data.dsize));
+ DEBUG(1, ("invalid lock record length %zu\n", data.dsize));
return false;
}
num_locks = data.dsize / sizeof(struct g_lock_rec);
--
2.1.4
From d83087478a8353b504c7164122278cf7d0679e1d Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 17 Feb 2016 14:01:47 +0100
Subject: [PATCH 12/12] idmap_script: Parallelize script calls
Fixes a case I've seen where a user with 200 group memberships timed out and
can now log in.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/winbindd/idmap_script.c | 622 ++++++++++++++++++++++++++++------------
1 file changed, 434 insertions(+), 188 deletions(-)
diff --git a/source3/winbindd/idmap_script.c b/source3/winbindd/idmap_script.c
index a929d6e..81603eb 100644
--- a/source3/winbindd/idmap_script.c
+++ b/source3/winbindd/idmap_script.c
@@ -36,6 +36,7 @@
#include "idmap_rw.h"
#include "../libcli/security/dom_sid.h"
#include "lib/util_file.h"
+#include "lib/util/tevent_unix.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_IDMAP
@@ -60,273 +61,518 @@ struct idmap_script_context {
TODO: Needs more validation ... like that we got a UID when we asked for one.
*/
-static NTSTATUS idmap_script_script(struct idmap_script_context *ctx,
- struct id_map *map, const char *fmt, ...)
-{
- va_list ap;
- char *cmd, **lines;
- int numlines = 0;
- unsigned long v;
- cmd = talloc_asprintf(ctx, "%s ", ctx->script);
- if (!cmd) {
- DEBUG(10, ("Unable to allocate memory for the script command!\n"));
- return NT_STATUS_NO_MEMORY;
- }
+struct idmap_script_xid2sid_state {
+ const char *syscmd;
+ size_t idx;
+ uint8_t *out;
+};
- va_start(ap, fmt);
- cmd = talloc_vasprintf_append(cmd, fmt, ap);
- va_end(ap);
- if (!cmd) {
- DEBUG(10, ("Unable to allocate memory for the script command!\n"));
- return NT_STATUS_NO_MEMORY;
+static void idmap_script_xid2sid_done(struct tevent_req *subreq);
+
+static struct tevent_req *idmap_script_xid2sid_send(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ struct unixid xid, const char *script, size_t idx)
+{
+ struct tevent_req *req, *subreq;
+ struct idmap_script_xid2sid_state *state;
+ char key;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct idmap_script_xid2sid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->idx = idx;
+
+ switch (xid.type) {
+ case ID_TYPE_UID:
+ key = 'U';
+ break;
+ case ID_TYPE_GID:
+ key = 'G';
+ break;
+ case ID_TYPE_BOTH:
+ key = 'X';
+ break;
+ default:
+ DBG_WARNING("INVALID unix ID type: 0x02%x\n", xid.type);
+ tevent_req_error(req, EINVAL);
+ return tevent_req_post(req, ev);
}
- lines = file_lines_pload(talloc_tos(), cmd, &numlines);
- talloc_free(cmd);
- if (!lines) {
- return NT_STATUS_NONE_MAPPED;
+ state->syscmd = talloc_asprintf(state, "%s %cID %lu", script, key,
+ (unsigned long)xid.id);
+ if (tevent_req_nomem(state->syscmd, req)) {
+ return tevent_req_post(req, ev);
}
- DEBUG(10,("idmap script gave %d lines, first: %s\n", numlines,
- lines[0]));
-
- if (sscanf(lines[0], "XID:%lu", &v) == 1) {
- map->xid.id = v;
- map->xid.type = ID_TYPE_BOTH;
- } else if (sscanf(lines[0], "UID:%lu", &v) == 1) {
- map->xid.id = v;
- map->xid.type = ID_TYPE_UID;
- } else if (sscanf(lines[0], "GID:%lu", &v) == 1) {
- map->xid.id = v;
- map->xid.type = ID_TYPE_GID;
- } else if (strncmp(lines[0], "SID:S-", 6) == 0) {
- if (!string_to_sid(map->sid, &lines[0][4])) {
- DEBUG(0,("Bad SID in '%s' from idmap script %s\n",
- lines[0], ctx->script));
- talloc_free(lines);
- return NT_STATUS_NONE_MAPPED;
- }
- } else {
- DEBUG(0,("Bad reply '%s' from idmap script %s\n",
- lines[0], ctx->script));
- talloc_free(lines);
- return NT_STATUS_NONE_MAPPED;
+ subreq = file_pload_send(state, ev, state->syscmd, 1024);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
+ tevent_req_set_callback(subreq, idmap_script_xid2sid_done, req);
+ return req;
+}
- talloc_free(lines);
- return NT_STATUS_OK;
+static void idmap_script_xid2sid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct idmap_script_xid2sid_state *state = tevent_req_data(
+ req, struct idmap_script_xid2sid_state);
+ int ret;
+
+ ret = file_pload_recv(subreq, state, &state->out);
+ TALLOC_FREE(subreq);
+ if (tevent_req_error(req, ret)) {
+ return;
+ }
+ tevent_req_done(req);
}
-/*
- Single id to sid lookup function.
-*/
-static NTSTATUS idmap_script_id_to_sid(struct idmap_domain *dom,
- struct id_map *map)
+static int idmap_script_xid2sid_recv(struct tevent_req *req, size_t *idx,
+ enum id_mapping *status,
+ struct dom_sid *sid)
{
- NTSTATUS ret;
- char *keystr;
- char *sidstr;
- struct idmap_script_context *ctx = dom->private_data;
+ struct idmap_script_xid2sid_state *state = tevent_req_data(
+ req, struct idmap_script_xid2sid_state);
+ char *out = (char *)state->out;
+ size_t out_size = talloc_get_size(out);
+ int err;
+
+ if (tevent_req_is_unix_error(req, &err)) {
+ return err;
+ }
- if (!dom || !map) {
- return NT_STATUS_INVALID_PARAMETER;
+ if (out_size == 0) {
+ goto unmapped;
+ }
+ if (state->out[out_size-1] != '\0') {
+ goto unmapped;
}
- /* apply filters before checking */
- if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
- DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
- map->xid.id, dom->low_id, dom->high_id));
- return NT_STATUS_NONE_MAPPED;
+ *idx = state->idx;
+
+ if ((strncmp(out, "SID:S-", 6) != 0) ||
+ !dom_sid_parse(out+4, sid)) {
+ DBG_WARNING("Bad sid from script: %s\n", out);
+ goto unmapped;
}
- switch (map->xid.type) {
+ *status = ID_MAPPED;
+ return 0;
- case ID_TYPE_UID:
- keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
- break;
+unmapped:
+ *sid = (struct dom_sid) {0};
+ *status = ID_UNMAPPED;
+ return 0;
+}
- case ID_TYPE_GID:
- keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
- break;
+struct idmap_script_xids2sids_state {
+ struct id_map **ids;
+ size_t num_ids;
+ size_t num_done;
+};
- case ID_TYPE_BOTH:
- keystr = talloc_asprintf(ctx, "XID %lu", (unsigned long)map->xid.id);
- break;
+static void idmap_script_xids2sids_done(struct tevent_req *subreq);
- default:
- DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
- return NT_STATUS_INVALID_PARAMETER;
+static struct tevent_req *idmap_script_xids2sids_send(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ struct id_map **ids, size_t num_ids, const char *script)
+{
+ struct tevent_req *req;
+ struct idmap_script_xids2sids_state *state;
+ size_t i;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct idmap_script_xids2sids_state);
+ if (req == NULL) {
+ return NULL;
}
+ state->ids = ids;
+ state->num_ids = num_ids;
- if (keystr == NULL) {
- DEBUG(0, ("Out of memory!\n"));
- ret = NT_STATUS_NO_MEMORY;
- goto done;
+ if (state->num_ids == 0) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
}
- DEBUG(10,("Running script to fetch mapping %s\n", keystr));
-
- ret = idmap_script_script(ctx, map, "IDTOSID %s", keystr);
- if (!NT_STATUS_IS_OK(ret)) {
- goto done;
- }
+ for (i=0; i<num_ids; i++) {
+ struct tevent_req *subreq;
- sidstr = sid_string_talloc(keystr, map->sid);
- if (!sidstr) {
- ret = NT_STATUS_NO_MEMORY;
- goto done;
+ subreq = idmap_script_xid2sid_send(
+ state, ev, ids[i]->xid, script, i);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, idmap_script_xids2sids_done,
+ req);
}
- DEBUG(10,("Found id %s:%d -> %s\n", keystr, map->xid.id,
- (const char *)sidstr));
- ret = NT_STATUS_OK;
-
-done:
- talloc_free(keystr);
- return ret;
+ return req;
}
-/*
- Single sid to id lookup function.
-*/
-static NTSTATUS idmap_script_sid_to_id(struct idmap_domain *dom,
- struct id_map *map)
+static void idmap_script_xids2sids_done(struct tevent_req *subreq)
{
- NTSTATUS ret;
- char *keystr;
- struct idmap_script_context *ctx = dom->private_data;
- TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct idmap_script_xids2sids_state *state = tevent_req_data(
+ req, struct idmap_script_xids2sids_state);
+ size_t idx = 0;
+ enum id_mapping status = ID_UNKNOWN;
+ struct dom_sid sid = {0};
+ int ret;
+
+ ret = idmap_script_xid2sid_recv(subreq, &idx, &status, &sid);
+ TALLOC_FREE(subreq);
+ if (tevent_req_error(req, ret)) {
+ return;
+ }
- keystr = sid_string_talloc(tmp_ctx, map->sid);
- if (keystr == NULL) {
- DEBUG(0, ("Out of memory!\n"));
- ret = NT_STATUS_NO_MEMORY;
- goto done;
+ if (idx >= state->num_ids) {
+ tevent_req_error(req, EINVAL);
+ return;
}
- DEBUG(10,("Fetching record %s\n", keystr));
+ state->ids[idx]->status = status;
- if (ctx->script == NULL) {
- ret = NT_STATUS_NONE_MAPPED;
- goto done;
+ state->ids[idx]->sid = dom_sid_dup(state->ids, &sid);
+ if (tevent_req_nomem(state->ids[idx]->sid, req)) {
+ return;
}
- ret = idmap_script_script(ctx, map, "SIDTOID %s", keystr);
- if (!NT_STATUS_IS_OK(ret)) {
- goto done;
- }
+ state->num_done += 1;
- /* apply filters before returning result */
- if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
- DEBUG(5, ("Script returned id (%u) out of range (%u - %u)."
- " Filtered!\n",
- map->xid.id, dom->low_id, dom->high_id));
- ret = NT_STATUS_NONE_MAPPED;
- goto done;
+ if (state->num_done >= state->num_ids) {
+ tevent_req_done(req);
}
+}
+
+static int idmap_script_xids2sids_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_unix(req);
+}
-done:
- talloc_free(tmp_ctx);
+static int idmap_script_xids2sids(struct id_map **ids, size_t num_ids,
+ const char *script)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ int ret = ENOMEM;
+
+ ev = samba_tevent_context_init(frame);
+ if (ev == NULL) {
+ goto fail;
+ }
+ req = idmap_script_xids2sids_send(frame, ev, ids, num_ids, script);
+ if (req == NULL) {
+ goto fail;
+ }
+ if (!tevent_req_poll(req, ev)) {
+ ret = errno;
+ goto fail;
+ }
+ ret = idmap_script_xids2sids_recv(req);
+fail:
+ TALLOC_FREE(frame);
return ret;
}
static NTSTATUS idmap_script_unixids_to_sids(struct idmap_domain *dom,
- struct id_map **ids)
+ struct id_map **ids)
{
- NTSTATUS ret;
- int i, num_mapped = 0;
+ struct idmap_script_context *ctx = talloc_get_type_abort(
+ dom->private_data, struct idmap_script_context);
+ int ret;
+ size_t i, num_ids, num_mapped;
DEBUG(10, ("%s called ...\n", __func__));
/* Init status to avoid surprise ... */
for (i = 0; ids[i]; i++) {
ids[i]->status = ID_UNKNOWN;
}
+ num_ids = i;
+
+ ret = idmap_script_xids2sids(ids, num_ids, ctx->script);
+ if (ret != 0) {
+ DBG_DEBUG("idmap_script_sids2xids returned %s\n",
+ strerror(ret));
+ return map_nt_error_from_unix(ret);
+ }
+
+ num_mapped = 0;
for (i = 0; ids[i]; i++) {
- ret = idmap_script_id_to_sid(dom, ids[i]);
- if (!NT_STATUS_IS_OK(ret)) {
- if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
- ids[i]->status = ID_UNMAPPED;
- continue;
- }
-
- /*
- * We cannot keep going if it is other than mapping
- * failed.
- */
- goto done;
+ if (ids[i]->status == ID_MAPPED) {
+ num_mapped += 1;
}
+ }
+
+ if (num_mapped == 0) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+ if (num_mapped < num_ids) {
+ return STATUS_SOME_UNMAPPED;
+ }
+ return NT_STATUS_OK;
+}
+
+struct idmap_script_sid2xid_state {
+ const char *syscmd;
+ size_t idx;
+ uint8_t *out;
+};
+
+static void idmap_script_sid2xid_done(struct tevent_req *subreq);
- ids[i]->status = ID_MAPPED;
- num_mapped++;
+static struct tevent_req *idmap_script_sid2xid_send(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ const struct dom_sid *sid, const char *script, size_t idx)
+{
+ struct tevent_req *req, *subreq;
+ struct idmap_script_sid2xid_state *state;
+ char sidbuf[DOM_SID_STR_BUFLEN];
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct idmap_script_sid2xid_state);
+ if (req == NULL) {
+ return NULL;
}
+ state->idx = idx;
- ret = NT_STATUS_OK;
+ dom_sid_string_buf(sid, sidbuf, sizeof(sidbuf));
-done:
- if (NT_STATUS_IS_OK(ret)) {
- if (i == 0 || num_mapped == 0) {
- ret = NT_STATUS_NONE_MAPPED;
- }
- else if (num_mapped < i) {
- ret = STATUS_SOME_UNMAPPED;
- } else {
- DEBUG(10, ("Returning NT_STATUS_OK\n"));
- ret = NT_STATUS_OK;
+ state->syscmd = talloc_asprintf(state, "%s SIDTOID %s",
+ script, sidbuf);
+ if (tevent_req_nomem(state->syscmd, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = file_pload_send(state, ev, state->syscmd, 1024);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, idmap_script_sid2xid_done, req);
+ return req;
+}
+
+static void idmap_script_sid2xid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct idmap_script_sid2xid_state *state = tevent_req_data(
+ req, struct idmap_script_sid2xid_state);
+ int ret;
+
+ ret = file_pload_recv(subreq, state, &state->out);
+ TALLOC_FREE(subreq);
+ if (tevent_req_error(req, ret)) {
+ return;
+ }
+ tevent_req_done(req);
+}
+
+static int idmap_script_sid2xid_recv(struct tevent_req *req,
+ size_t *idx, enum id_mapping *status,
+ struct unixid *xid)
+{
+ struct idmap_script_sid2xid_state *state = tevent_req_data(
+ req, struct idmap_script_sid2xid_state);
+ char *out = (char *)state->out;
+ size_t out_size = talloc_get_size(out);
+ unsigned long v;
+ int err;
+
+ if (tevent_req_is_unix_error(req, &err)) {
+ return err;
+ }
+
+ if (out_size == 0) {
+ goto unmapped;
+ }
+ if (state->out[out_size-1] != '\0') {
+ goto unmapped;
+ }
+
+ *idx = state->idx;
+
+ if (sscanf(out, "XID:%lu\n", &v) == 1) {
+ *xid = (struct unixid) { .id = v, .type = ID_TYPE_BOTH };
+ } else if (sscanf(out, "UID:%lu\n", &v) == 1) {
+ *xid = (struct unixid) { .id = v, .type = ID_TYPE_UID };
+ } else if (sscanf(out, "GID:%lu\n", &v) == 1) {
+ *xid = (struct unixid) { .id = v, .type = ID_TYPE_GID };
+ } else {
+ goto unmapped;
+ }
+
+ *status = ID_MAPPED;
+ return 0;
+
+unmapped:
+ *xid = (struct unixid) { .id = UINT32_MAX,
+ .type = ID_TYPE_NOT_SPECIFIED };
+ *status = ID_UNMAPPED;
+ return 0;
+}
+
+struct idmap_script_sids2xids_state {
+ struct id_map **ids;
+ size_t num_ids;
+ size_t num_done;
+};
+
+static void idmap_script_sids2xids_done(struct tevent_req *subreq);
+
+static struct tevent_req *idmap_script_sids2xids_send(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ struct id_map **ids, size_t num_ids, const char *script)
+{
+ struct tevent_req *req;
+ struct idmap_script_sids2xids_state *state;
+ size_t i;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct idmap_script_sids2xids_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ids = ids;
+ state->num_ids = num_ids;
+
+ if (state->num_ids == 0) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
+ for (i=0; i<num_ids; i++) {
+ struct tevent_req *subreq;
+
+ subreq = idmap_script_sid2xid_send(
+ state, ev, ids[i]->sid, script, i);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
+ tevent_req_set_callback(subreq, idmap_script_sids2xids_done,
+ req);
+ }
+
+ return req;
+}
+
+static void idmap_script_sids2xids_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct idmap_script_sids2xids_state *state = tevent_req_data(
+ req, struct idmap_script_sids2xids_state);
+ size_t idx = 0;
+ enum id_mapping status = ID_UNKNOWN;
+ struct unixid xid = { .id = UINT32_MAX,
+ .type = ID_TYPE_NOT_SPECIFIED };
+ int ret;
+
+ ret = idmap_script_sid2xid_recv(subreq, &idx, &status, &xid);
+ TALLOC_FREE(subreq);
+ if (tevent_req_error(req, ret)) {
+ return;
+ }
+
+ if (idx >= state->num_ids) {
+ tevent_req_error(req, EINVAL);
+ return;
}
+ state->ids[idx]->status = status;
+ state->ids[idx]->xid = xid;
+
+ state->num_done += 1;
+
+ if (state->num_done >= state->num_ids) {
+ tevent_req_done(req);
+ }
+}
+
+static int idmap_script_sids2xids_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_unix(req);
+}
+
+static int idmap_script_sids2xids(struct id_map **ids, size_t num_ids,
+ const char *script)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ int ret = ENOMEM;
+
+ ev = samba_tevent_context_init(frame);
+ if (ev == NULL) {
+ goto fail;
+ }
+ req = idmap_script_sids2xids_send(frame, ev, ids, num_ids, script);
+ if (req == NULL) {
+ goto fail;
+ }
+ if (!tevent_req_poll(req, ev)) {
+ ret = errno;
+ goto fail;
+ }
+ ret = idmap_script_sids2xids_recv(req);
+fail:
+ TALLOC_FREE(frame);
return ret;
}
static NTSTATUS idmap_script_sids_to_unixids(struct idmap_domain *dom,
- struct id_map **ids)
+ struct id_map **ids)
{
- NTSTATUS ret;
- int i, num_mapped = 0;
+ struct idmap_script_context *ctx = talloc_get_type_abort(
+ dom->private_data, struct idmap_script_context);
+ int ret;
+ size_t i, num_ids, num_mapped;
DEBUG(10, ("%s called ...\n", __func__));
/* Init status to avoid surprise ... */
for (i = 0; ids[i]; i++) {
ids[i]->status = ID_UNKNOWN;
}
+ num_ids = i;
- for (i = 0; ids[i]; i++) {
- ret = idmap_script_sid_to_id(dom, ids[i]);
- if (!NT_STATUS_IS_OK(ret)) {
- if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
- ids[i]->status = ID_UNMAPPED;
- continue;
- }
-
- /*
- * We cannot keep going if it is other than mapping
- * failed.
- */
- goto done;
- }
-
- ids[i]->status = ID_MAPPED;
- num_mapped++;
+ ret = idmap_script_sids2xids(ids, num_ids, ctx->script);
+ if (ret != 0) {
+ DBG_DEBUG("idmap_script_sids2xids returned %s\n",
+ strerror(ret));
+ return map_nt_error_from_unix(ret);
}
- ret = NT_STATUS_OK;
+ num_mapped = 0;
-done:
- if (NT_STATUS_IS_OK(ret)) {
- if (i == 0 || num_mapped == 0) {
- ret = NT_STATUS_NONE_MAPPED;
+ for (i=0; i<num_ids; i++) {
+ struct id_map *map = ids[i];
+
+ if ((map->status == ID_MAPPED) &&
+ !idmap_unix_id_is_in_range(map->xid.id, dom)) {
+ DBG_INFO("Script returned id (%u) out of range "
+ "(%u - %u). Filtered!\n",
+ map->xid.id, dom->low_id, dom->high_id);
+ map->status = ID_UNMAPPED;
}
- else if (num_mapped < i) {
- ret = STATUS_SOME_UNMAPPED;
- } else {
- DEBUG(10, ("Returning NT_STATUS_OK\n"));
- ret = NT_STATUS_OK;
+
+ if (map->status == ID_MAPPED) {
+ num_mapped += 1;
}
}
- return ret;
+ if (num_mapped == 0) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+ if (num_mapped < num_ids) {
+ return STATUS_SOME_UNMAPPED;
+ }
+ return NT_STATUS_OK;
}
/*
--
2.1.4
More information about the samba-technical
mailing list