diff options
Diffstat (limited to 'source4/lib/util')
-rw-r--r-- | source4/lib/util/dprintf.c | 39 | ||||
-rw-r--r-- | source4/lib/util/ms_fnmatch.c | 15 | ||||
-rw-r--r-- | source4/lib/util/smbrun.c | 341 | ||||
-rw-r--r-- | source4/lib/util/tests/strlist.c | 25 | ||||
-rw-r--r-- | source4/lib/util/util.h | 1 | ||||
-rw-r--r-- | source4/lib/util/util_ldb.c | 6 | ||||
-rw-r--r-- | source4/lib/util/util_strlist.c | 10 | ||||
-rw-r--r-- | source4/lib/util/util_tdb.c | 17 |
8 files changed, 71 insertions, 383 deletions
diff --git a/source4/lib/util/dprintf.c b/source4/lib/util/dprintf.c index 5b3fe4b1ea..308d81b105 100644 --- a/source4/lib/util/dprintf.c +++ b/source4/lib/util/dprintf.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. display print functions Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2007 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 @@ -32,13 +33,26 @@ #include "includes.h" #include "system/locale.h" +#include "param/param.h" + +static smb_iconv_t display_cd = (smb_iconv_t)-1; + +void d_set_iconv(smb_iconv_t cd) +{ + display_cd = cd; +} _PUBLIC_ int d_vfprintf(FILE *f, const char *format, va_list ap) _PRINTF_ATTRIBUTE(2,0) { char *p, *p2; - int ret, maxlen, clen; + int ret, clen; va_list ap2; + /* If there's nothing to convert, take a shortcut */ + if (display_cd == (smb_iconv_t)-1) { + return vfprintf(f, format, ap); + } + /* do any message translations */ va_copy(ap2, ap); ret = vasprintf(&p, format, ap2); @@ -46,16 +60,7 @@ _PUBLIC_ int d_vfprintf(FILE *f, const char *format, va_list ap) _PRINTF_ATTRIBU if (ret <= 0) return ret; - /* now we have the string in unix format, convert it to the display - charset, but beware of it growing */ - maxlen = ret*2; -again: - p2 = (char *)malloc(maxlen); - if (!p2) { - SAFE_FREE(p); - return -1; - } - clen = convert_string(global_smb_iconv_convenience, CH_UNIX, CH_DISPLAY, p, ret, p2, maxlen); + clen = convert_string_talloc_descriptor(NULL, display_cd, p, ret, (void **)&p2); if (clen == -1) { /* the string can't be converted - do the best we can, filling in non-printing chars with '?' */ @@ -68,22 +73,13 @@ again: } } SAFE_FREE(p); - SAFE_FREE(p2); return ret; } - - if (clen >= maxlen) { - /* it didn't fit - try a larger buffer */ - maxlen *= 2; - SAFE_FREE(p2); - goto again; - } - /* good, its converted OK */ SAFE_FREE(p); ret = fwrite(p2, 1, clen, f); - SAFE_FREE(p2); + talloc_free(p2); return ret; } @@ -112,3 +108,4 @@ _PUBLIC_ int d_printf(const char *format, ...) _PRINTF_ATTRIBUTE(1,2) return ret; } + diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c index e1bf6f94c5..1fb57b07a4 100644 --- a/source4/lib/util/ms_fnmatch.c +++ b/source4/lib/util/ms_fnmatch.c @@ -29,6 +29,7 @@ */ #include "includes.h" +#include "param/param.h" static int null_match(const char *p) { @@ -64,7 +65,7 @@ static int ms_fnmatch_core(const char *p, const char *n, int i; size_t size, size_n; - while ((c = next_codepoint(global_smb_iconv_convenience, p, &size))) { + while ((c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &size))) { p += size; switch (c) { @@ -74,7 +75,7 @@ static int ms_fnmatch_core(const char *p, const char *n, return null_match(p); } for (i=0; n[i]; i += size_n) { - next_codepoint(global_smb_iconv_convenience, n+i, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n+i, &size_n); if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { return 0; } @@ -93,7 +94,7 @@ static int ms_fnmatch_core(const char *p, const char *n, return -1; } for (i=0; n[i]; i += size_n) { - next_codepoint(global_smb_iconv_convenience, n+i, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n+i, &size_n); if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) return 0; if (n+i == ldot) { if (ms_fnmatch_core(p, n+i+size_n, max_n+1, ldot) == 0) return 0; @@ -109,7 +110,7 @@ static int ms_fnmatch_core(const char *p, const char *n, if (! *n) { return -1; } - next_codepoint(global_smb_iconv_convenience, n, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); n += size_n; break; @@ -123,7 +124,7 @@ static int ms_fnmatch_core(const char *p, const char *n, break; } if (! *n) return null_match(p); - next_codepoint(global_smb_iconv_convenience, n, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); n += size_n; break; @@ -133,12 +134,12 @@ static int ms_fnmatch_core(const char *p, const char *n, return 0; } if (*n != '.') return -1; - next_codepoint(global_smb_iconv_convenience, n, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); n += size_n; break; default: - c2 = next_codepoint(global_smb_iconv_convenience, n, &size_n); + c2 = next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); if (c != c2 && codepoint_cmpi(c, c2) != 0) { return -1; } diff --git a/source4/lib/util/smbrun.c b/source4/lib/util/smbrun.c deleted file mode 100644 index 26330ab992..0000000000 --- a/source4/lib/util/smbrun.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - Unix SMB/CIFS implementation. - run a command as a specified user - Copyright (C) Andrew Tridgell 1992-1998 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -/* need to move this from here!! need some sleep ... */ -struct current_user current_user; - -/**************************************************************************** -This is a utility function of smbrun(). -****************************************************************************/ - -static int setup_out_fd(void) -{ - int fd; - TALLOC_CTX *ctx = talloc_stackframe(); - char *path = NULL; - - path = talloc_asprintf(ctx, - "%s/smb.XXXXXX", - tmpdir()); - if (!path) { - TALLOC_FREE(ctx); - errno = ENOMEM; - return -1; - } - - /* now create the file */ - fd = smb_mkstemp(path); - - if (fd == -1) { - DEBUG(0,("setup_out_fd: Failed to create file %s. (%s)\n", - path, strerror(errno) )); - TALLOC_FREE(ctx); - return -1; - } - - DEBUG(10,("setup_out_fd: Created tmp file %s\n", path )); - - /* Ensure file only kept around by open fd. */ - unlink(path); - TALLOC_FREE(ctx); - return fd; -} - -/**************************************************************************** -run a command being careful about uid/gid handling and putting the output in -outfd (or discard it if outfd is NULL). -****************************************************************************/ - -static int smbrun_internal(const char *cmd, int *outfd, BOOL sanitize) -{ - pid_t pid; - uid_t uid = current_user.ut.uid; - gid_t gid = current_user.ut.gid; - - /* - * Lose any elevated privileges. - */ - drop_effective_capability(KERNEL_OPLOCK_CAPABILITY); - drop_effective_capability(DMAPI_ACCESS_CAPABILITY); - - /* point our stdout at the file we want output to go into */ - - if (outfd && ((*outfd = setup_out_fd()) == -1)) { - return -1; - } - - /* in this method we will exec /bin/sh with the correct - arguments, after first setting stdout to point at the file */ - - /* - * We need to temporarily stop CatchChild from eating - * SIGCLD signals as it also eats the exit status code. JRA. - */ - - CatchChildLeaveStatus(); - - if ((pid=sys_fork()) < 0) { - DEBUG(0,("smbrun: fork failed with error %s\n", strerror(errno) )); - CatchChild(); - if (outfd) { - close(*outfd); - *outfd = -1; - } - return errno; - } - - if (pid) { - /* - * Parent. - */ - int status=0; - pid_t wpid; - - - /* the parent just waits for the child to exit */ - while((wpid = sys_waitpid(pid,&status,0)) < 0) { - if(errno == EINTR) { - errno = 0; - continue; - } - break; - } - - CatchChild(); - - if (wpid != pid) { - DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno))); - if (outfd) { - close(*outfd); - *outfd = -1; - } - return -1; - } - - /* Reset the seek pointer. */ - if (outfd) { - sys_lseek(*outfd, 0, SEEK_SET); - } - -#if defined(WIFEXITED) && defined(WEXITSTATUS) - if (WIFEXITED(status)) { - return WEXITSTATUS(status); - } -#endif - - return status; - } - - CatchChild(); - - /* we are in the child. we exec /bin/sh to do the work for us. we - don't directly exec the command we want because it may be a - pipeline or anything else the config file specifies */ - - /* point our stdout at the file we want output to go into */ - if (outfd) { - close(1); - if (sys_dup2(*outfd,1) != 1) { - DEBUG(2,("Failed to create stdout file descriptor\n")); - close(*outfd); - exit(80); - } - } - - /* now completely lose our privileges. This is a fairly paranoid - way of doing it, but it does work on all systems that I know of */ - - become_user_permanently(uid, gid); - - if (getuid() != uid || geteuid() != uid || - getgid() != gid || getegid() != gid) { - /* we failed to lose our privileges - do not execute - the command */ - exit(81); /* we can't print stuff at this stage, - instead use exit codes for debugging */ - } - -#ifndef __INSURE__ - /* close all other file descriptors, leaving only 0, 1 and 2. 0 and - 2 point to /dev/null from the startup code */ - { - int fd; - for (fd=3;fd<256;fd++) close(fd); - } -#endif - - { - const char *newcmd = sanitize ? escape_shell_string(cmd) : cmd; - if (!newcmd) { - exit(82); - } - execl("/bin/sh","sh","-c",newcmd,NULL); - } - - /* not reached */ - exit(83); - return 1; -} - -/**************************************************************************** - Use only in known safe shell calls (printing). -****************************************************************************/ - -int smbrun_no_sanitize(const char *cmd, int *outfd) -{ - return smbrun_internal(cmd, outfd, False); -} - -/**************************************************************************** - By default this now sanitizes shell expansion. -****************************************************************************/ - -int smbrun(const char *cmd, int *outfd) -{ - return smbrun_internal(cmd, outfd, True); -} - -/**************************************************************************** -run a command being careful about uid/gid handling and putting the output in -outfd (or discard it if outfd is NULL). -sends the provided secret to the child stdin. -****************************************************************************/ - -int smbrunsecret(const char *cmd, const char *secret) -{ - pid_t pid; - uid_t uid = current_user.ut.uid; - gid_t gid = current_user.ut.gid; - int ifd[2]; - - /* - * Lose any elevated privileges. - */ - drop_effective_capability(KERNEL_OPLOCK_CAPABILITY); - drop_effective_capability(DMAPI_ACCESS_CAPABILITY); - - /* build up an input pipe */ - if(pipe(ifd)) { - return -1; - } - - /* in this method we will exec /bin/sh with the correct - arguments, after first setting stdout to point at the file */ - - /* - * We need to temporarily stop CatchChild from eating - * SIGCLD signals as it also eats the exit status code. JRA. - */ - - CatchChildLeaveStatus(); - - if ((pid=sys_fork()) < 0) { - DEBUG(0, ("smbrunsecret: fork failed with error %s\n", strerror(errno))); - CatchChild(); - return errno; - } - - if (pid) { - /* - * Parent. - */ - int status = 0; - pid_t wpid; - size_t towrite; - ssize_t wrote; - - close(ifd[0]); - /* send the secret */ - towrite = strlen(secret); - wrote = write(ifd[1], secret, towrite); - if ( wrote != towrite ) { - DEBUG(0,("smbrunsecret: wrote %ld of %lu bytes\n",(long)wrote,(unsigned long)towrite)); - } - fsync(ifd[1]); - close(ifd[1]); - - /* the parent just waits for the child to exit */ - while((wpid = sys_waitpid(pid, &status, 0)) < 0) { - if(errno == EINTR) { - errno = 0; - continue; - } - break; - } - - CatchChild(); - - if (wpid != pid) { - DEBUG(2, ("waitpid(%d) : %s\n", (int)pid, strerror(errno))); - return -1; - } - -#if defined(WIFEXITED) && defined(WEXITSTATUS) - if (WIFEXITED(status)) { - return WEXITSTATUS(status); - } -#endif - - return status; - } - - CatchChild(); - - /* we are in the child. we exec /bin/sh to do the work for us. we - don't directly exec the command we want because it may be a - pipeline or anything else the config file specifies */ - - close(ifd[1]); - close(0); - if (sys_dup2(ifd[0], 0) != 0) { - DEBUG(2,("Failed to create stdin file descriptor\n")); - close(ifd[0]); - exit(80); - } - - /* now completely lose our privileges. This is a fairly paranoid - way of doing it, but it does work on all systems that I know of */ - - become_user_permanently(uid, gid); - - if (getuid() != uid || geteuid() != uid || - getgid() != gid || getegid() != gid) { - /* we failed to lose our privileges - do not execute - the command */ - exit(81); /* we can't print stuff at this stage, - instead use exit codes for debugging */ - } - -#ifndef __INSURE__ - /* close all other file descriptors, leaving only 0, 1 and 2. 0 and - 2 point to /dev/null from the startup code */ - { - int fd; - for (fd = 3; fd < 256; fd++) close(fd); - } -#endif - - execl("/bin/sh", "sh", "-c", cmd, NULL); - - /* not reached */ - exit(82); - return 1; -} diff --git a/source4/lib/util/tests/strlist.c b/source4/lib/util/tests/strlist.c index 437d9d741a..3ecb982e24 100644 --- a/source4/lib/util/tests/strlist.c +++ b/source4/lib/util/tests/strlist.c @@ -64,6 +64,29 @@ static bool test_lists_shell(struct torture_context *tctx, return true; } +static bool test_list_copy(struct torture_context *tctx) +{ + const char **result; + const char *list[] = { "foo", "bar", NULL }; + const char *empty_list[] = { NULL }; + const char **null_list = NULL; + + result = str_list_copy(tctx, list); + torture_assert_int_equal(tctx, str_list_length(result), 2, "list length"); + torture_assert_str_equal(tctx, result[0], "foo", "element 0"); + torture_assert_str_equal(tctx, result[1], "bar", "element 1"); + torture_assert_str_equal(tctx, result[2], NULL, "element 2"); + + result = str_list_copy(tctx, empty_list); + torture_assert_int_equal(tctx, str_list_length(result), 0, "list length"); + torture_assert_str_equal(tctx, result[0], NULL, "element 0"); + + result = str_list_copy(tctx, null_list); + torture_assert(tctx, result == NULL, "result NULL"); + + return true; +} + struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx) { struct torture_suite *suite = torture_suite_create(mem_ctx, "STRLIST"); @@ -75,5 +98,7 @@ struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx) &test_lists_shell_strings[i]); } + torture_suite_add_simple_test(suite, "list_copy", test_list_copy); + return suite; } diff --git a/source4/lib/util/util.h b/source4/lib/util/util.h index f3adbb3333..9e106052f2 100644 --- a/source4/lib/util/util.h +++ b/source4/lib/util/util.h @@ -262,6 +262,7 @@ _PUBLIC_ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len); /* The following definitions come from lib/util/dprintf.c */ +_PUBLIC_ void d_set_iconv(smb_iconv_t); _PUBLIC_ int d_vfprintf(FILE *f, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); _PUBLIC_ int d_fprintf(FILE *f, const char *format, ...) PRINTF_ATTRIBUTE(2,3); _PUBLIC_ int d_printf(const char *format, ...) PRINTF_ATTRIBUTE(1,2); diff --git a/source4/lib/util/util_ldb.c b/source4/lib/util/util_ldb.c index ba8443c236..a8719af190 100644 --- a/source4/lib/util/util_ldb.c +++ b/source4/lib/util/util_ldb.c @@ -23,16 +23,16 @@ #include "includes.h" #include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb_errors.h" - +#include "lib/util/util_ldb.h" /* search the sam for the specified attributes - va_list variant */ -int gendb_search_v(struct ldb_context *ldb, +int gendb_search_v(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *basedn, struct ldb_message ***msgs, const char * const *attrs, - const char *format, + const char *format, va_list ap) _PRINTF_ATTRIBUTE(6,0) { enum ldb_scope scope = LDB_SCOPE_SUBTREE; diff --git a/source4/lib/util/util_strlist.c b/source4/lib/util/util_strlist.c index 1f1cc17d00..30de4b962d 100644 --- a/source4/lib/util/util_strlist.c +++ b/source4/lib/util/util_strlist.c @@ -199,8 +199,14 @@ _PUBLIC_ size_t str_list_length(const char **list) _PUBLIC_ const char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list) { int i; - const char **ret = talloc_array(mem_ctx, const char *, str_list_length(list)+1); - if (ret == NULL) return NULL; + const char **ret; + + if (list == NULL) + return NULL; + + ret = talloc_array(mem_ctx, const char *, str_list_length(list)+1); + if (ret == NULL) + return NULL; for (i=0;list && list[i];i++) { ret[i] = talloc_strdup(ret, list[i]); diff --git a/source4/lib/util/util_tdb.c b/source4/lib/util/util_tdb.c index d7bddbde01..77ad4eb617 100644 --- a/source4/lib/util/util_tdb.c +++ b/source4/lib/util/util_tdb.c @@ -445,7 +445,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) int len; int *i; void **p; - char *s, **b; + char *s, **b, **ps; char c; char *buf0 = buf; const char *fmt0 = fmt; @@ -453,7 +453,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) tdb_log_func log_fn = tdb_log_fn(tdb); va_start(ap, fmt); - + while (*fmt) { switch ((c=*fmt++)) { case 'b': @@ -485,11 +485,10 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) *p = (void *)IVAL(buf, 0); break; case 'P': - s = va_arg(ap,char *); - len = strlen(buf) + 1; - if (bufsize < len || len > sizeof(pstring)) - goto no_space; - memcpy(s, buf, len); + /* Return a malloc'ed string. */ + ps = va_arg(ap,char ** ); + len = strlen((const char *)buf) + 1; + *ps = strdup((const char *)buf); break; case 'f': s = va_arg(ap,char *); @@ -518,7 +517,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) memcpy(*b, buf+4, *i); break; default: - log_fn(tdb, 0, "Unknown tdb_unpack format %c in %s\n", + log_fn(tdb, 0, "Unknown tdb_unpack format %c in %s\n", c, fmt); len = 0; @@ -531,7 +530,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) va_end(ap); - log_fn(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", + log_fn(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); return PTR_DIFF(buf, buf0); |