summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/access.c3
-rw-r--r--source3/lib/afs.c248
-rw-r--r--source3/lib/charcnv.c331
-rw-r--r--source3/lib/dummyroot.c33
-rw-r--r--source3/lib/fault.c2
-rw-r--r--source3/lib/gencache.c9
-rw-r--r--source3/lib/hash.c15
-rw-r--r--source3/lib/module.c30
-rw-r--r--source3/lib/ms_fnmatch.c82
-rw-r--r--source3/lib/popt_common.c35
-rw-r--r--source3/lib/readline.c4
-rw-r--r--source3/lib/replace1.c42
-rw-r--r--source3/lib/smbldap.c27
-rw-r--r--source3/lib/substitute.c31
-rw-r--r--source3/lib/system.c159
-rw-r--r--source3/lib/util.c81
-rw-r--r--source3/lib/util_file.c5
-rw-r--r--source3/lib/util_sid.c2
-rw-r--r--source3/lib/util_str.c202
-rw-r--r--source3/lib/version.c42
20 files changed, 1158 insertions, 225 deletions
diff --git a/source3/lib/access.c b/source3/lib/access.c
index c30b3c33cc..a874c8b1e2 100644
--- a/source3/lib/access.c
+++ b/source3/lib/access.c
@@ -281,13 +281,12 @@ static BOOL only_ipaddrs_in_list(const char** list)
}
if (!is_ipaddress(*list)) {
- char *p;
/*
* if we failed, make sure that it was not because the token
* was a network/netmask pair. Only network/netmask pairs
* have a '/' in them
*/
- if ((p=strchr_m(*list, '/')) == NULL) {
+ if ((strchr_m(*list, '/')) == NULL) {
only_ip = False;
DEBUG(3,("only_ipaddrs_in_list: list has non-ip address (%s)\n", *list));
break;
diff --git a/source3/lib/afs.c b/source3/lib/afs.c
new file mode 100644
index 0000000000..b96703e986
--- /dev/null
+++ b/source3/lib/afs.c
@@ -0,0 +1,248 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Generate AFS tickets
+ * Copyright (C) Volker Lendecke 2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#ifdef WITH_FAKE_KASERVER
+
+#include <afs/stds.h>
+#include <afs/afs.h>
+#include <afs/auth.h>
+#include <afs/venus.h>
+#include <asm/unistd.h>
+#include <openssl/des.h>
+
+_syscall5(int, afs_syscall, int, subcall,
+ char *, path,
+ int, cmd,
+ char *, cmarg,
+ int, follow);
+
+char *afs_cell(void)
+{
+ static char *cell = NULL;
+
+ if (cell == NULL) {
+ cell = strdup(lp_realm());
+ strlower_m(cell);
+ }
+
+ return cell;
+}
+
+struct ClearToken {
+ uint32 AuthHandle;
+ char HandShakeKey[8];
+ uint32 ViceId;
+ uint32 BeginTimestamp;
+ uint32 EndTimestamp;
+};
+
+/*
+ Put an AFS token into the Kernel so that it can authenticate against
+ the AFS server. This assumes correct local uid settings.
+
+ This is currently highly Linux and OpenAFS-specific. The correct API
+ call for this would be ktc_SetToken. But to do that we would have to
+ import a REALLY big bunch of libraries which I would currently like
+ to avoid.
+*/
+
+static BOOL afs_settoken(char *username, const struct ClearToken *ctok,
+ char *v4tkt_data, int v4tkt_length)
+{
+ int ret;
+ struct {
+ char *in, *out;
+ uint16 in_size, out_size;
+ } iob;
+
+ char buf[1024];
+ char *p = buf;
+ int tmp;
+
+ memcpy(p, &v4tkt_length, sizeof(uint32));
+ p += sizeof(uint32);
+ memcpy(p, v4tkt_data, v4tkt_length);
+ p += v4tkt_length;
+
+ tmp = sizeof(struct ClearToken);
+ memcpy(p, &tmp, sizeof(uint32));
+ p += sizeof(uint32);
+ memcpy(p, ctok, tmp);
+ p += tmp;
+
+ tmp = 0;
+
+ memcpy(p, &tmp, sizeof(uint32));
+ p += sizeof(uint32);
+
+ tmp = strlen(afs_cell());
+ if (tmp >= MAXKTCREALMLEN) {
+ DEBUG(1, ("Realm too long\n"));
+ return False;
+ }
+
+ strncpy(p, afs_cell(), tmp);
+ p += tmp;
+ *p = 0;
+ p +=1;
+
+ iob.in = buf;
+ iob.in_size = PTR_DIFF(p,buf);
+ iob.out = buf;
+ iob.out_size = sizeof(buf);
+
+#if 0
+ file_save("/tmp/ioctlbuf", iob.in, iob.in_size);
+#endif
+
+ ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0);
+
+ DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret));
+ return (ret == 0);
+}
+
+/*
+ This routine takes a radical approach completely defeating the
+ Kerberos idea of security and using AFS simply as an intelligent
+ file backend. Samba has persuaded itself somehow that the user is
+ actually correctly identified and then we create a ticket that the
+ AFS server hopefully accepts using its KeyFile that the admin has
+ kindly stored to our secrets.tdb.
+
+ Thanks to the book "Network Security -- PRIVATE Communication in a
+ PUBLIC World" by Charlie Kaufman, Radia Perlman and Mike Speciner
+ Kerberos 4 tickets are not really hard to construct.
+
+ For the comments "Alice" is the User to be auth'ed, and "Bob" is the
+ AFS server. */
+
+BOOL afs_login(char *username)
+{
+ fstring ticket;
+ char *p = ticket;
+ uint32 len;
+ struct afs_key key;
+
+ struct ClearToken ct;
+
+ uint32 now; /* I assume time() returns 32 bit */
+
+ des_key_schedule key_schedule;
+
+ DEBUG(10, ("Trying to log into AFS for user %s@%s\n",
+ username, afs_cell()));
+
+ if (!secrets_init())
+ return False;
+
+ if (!secrets_fetch_afs_key(afs_cell(), &key)) {
+ DEBUG(5, ("Could not fetch AFS service key\n"));
+ return False;
+ }
+
+ ct.AuthHandle = key.kvno;
+
+ /* Build the ticket. This is going to be encrypted, so in our
+ way we fill in ct while we still have the unencrypted
+ form. */
+
+ p = ticket;
+
+ /* The byte-order */
+ *p = 1;
+ p += 1;
+
+ /* "Alice", the client username */
+ strncpy(p, username, sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ p += strlen(p)+1;
+ strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ p += strlen(p)+1;
+ strncpy(p, afs_cell(), sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ p += strlen(p)+1;
+
+ ct.ViceId = getuid();
+ DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId));
+
+ /* Alice's network layer address. At least Openafs-1.2.10
+ ignores this, so we fill in a dummy value here. */
+ SIVAL(p, 0, 0);
+ p += 4;
+
+ /* We need to create a session key */
+ generate_random_buffer(p, 8, False);
+
+ /* Our client code needs the the key in the clear, it does not
+ know the server-key ... */
+ memcpy(ct.HandShakeKey, p, 8);
+
+ p += 8;
+
+ /* Ticket lifetime. We fake everything here, so go as long as
+ possible. This is in 5-minute intervals, so 255 is 21 hours
+ and 15 minutes.*/
+ *p = 255;
+ p += 1;
+
+ /* Ticket creation time */
+ now = time(NULL);
+ SIVAL(p, 0, now);
+ ct.BeginTimestamp = now;
+
+ ct.EndTimestamp = now + (255*60*5);
+ if (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1) {
+ ct.BeginTimestamp += 1; /* Lifetime must be even */
+ }
+ p += 4;
+
+ /* And here comes Bob's name and instance, in this case the
+ AFS server. */
+ strncpy(p, "afs", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ p += strlen(p)+1;
+ strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ p += strlen(p)+1;
+
+ /* And zero-pad to a multiple of 8 bytes */
+ len = PTR_DIFF(p, ticket);
+ if (len & 7) {
+ uint32 extra_space = 8-(len & 7);
+ memset(p, 0, extra_space);
+ p+=extra_space;
+ }
+ len = PTR_DIFF(p, ticket);
+
+ des_key_sched((const_des_cblock *)key.key, key_schedule);
+ des_pcbc_encrypt(ticket, ticket,
+ len, key_schedule, (C_Block *)key.key, 1);
+
+ ZERO_STRUCT(key);
+
+ return afs_settoken(username, &ct, ticket, len);
+}
+
+#else
+
+BOOL afs_login(char *username)
+{
+ return True;
+}
+
+#endif /* WITH_FAKE_KASERVER */
diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c
index ca5e378970..5f3cf64a68 100644
--- a/source3/lib/charcnv.c
+++ b/source3/lib/charcnv.c
@@ -40,7 +40,7 @@
static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
-
+static BOOL conv_silent; /* Should we do a debug if the conversion fails ? */
/**
* Return the name of a charset to give to iconv().
@@ -141,21 +141,28 @@ void init_iconv(void)
/* XXX: Does this really get called every time the dos
* codepage changes? */
/* XXX: Is the did_reload test too strict? */
+ conv_silent = True;
init_doschar_table();
init_valid_table();
+ conv_silent = False;
}
}
/**
* Convert string from one encoding to another, making error checking etc
+ * Slow path version - uses (slow) iconv.
*
* @param src pointer to source string (multibyte or singlebyte)
* @param srclen length of the source string in bytes
* @param dest pointer to destination string (multibyte or singlebyte)
* @param destlen maximal length allowed for string
* @returns the number of bytes occupied in the destination
+ *
+ * Ensure the srclen contains the terminating zero.
+ *
**/
-size_t convert_string(charset_t from, charset_t to,
+
+static size_t convert_string_internal(charset_t from, charset_t to,
void const *src, size_t srclen,
void *dest, size_t destlen)
{
@@ -165,18 +172,14 @@ size_t convert_string(charset_t from, charset_t to,
char* outbuf = (char*)dest;
smb_iconv_t descriptor;
- if (srclen == (size_t)-1)
- srclen = strlen(src)+1;
-
lazy_initialize_conv();
descriptor = conv_handles[from][to];
if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
- /* conversion not supported, use as is */
- size_t len = MIN(srclen,destlen);
- memcpy(dest,src,len);
- return len;
+ if (!conv_silent)
+ DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
+ goto use_as_is;
}
i_len=srclen;
@@ -187,67 +190,208 @@ size_t convert_string(charset_t from, charset_t to,
switch(errno) {
case EINVAL:
reason="Incomplete multibyte sequence";
- break;
+ if (!conv_silent)
+ DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
+ goto use_as_is;
case E2BIG:
reason="No more room";
- DEBUG(0, ("convert_string: Required %lu, available %lu\n",
- (unsigned long)srclen, (unsigned long)destlen));
+ if (!conv_silent)
+ DEBUG(3, ("convert_string_internal: Required %lu, available %lu\n",
+ (unsigned long)srclen, (unsigned long)destlen));
/* we are not sure we need srclen bytes,
may be more, may be less.
We only know we need more than destlen
bytes ---simo */
break;
case EILSEQ:
- reason="Illegal multibyte sequence";
- break;
+ reason="Illegal multibyte sequence";
+ if (!conv_silent)
+ DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
+ goto use_as_is;
+ default:
+ if (!conv_silent)
+ DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
+ break;
}
/* smb_panic(reason); */
}
return destlen-o_len;
+
+ use_as_is:
+
+ /* conversion not supported, use as is */
+ {
+ size_t len = MIN(srclen,destlen);
+ if (len)
+ memcpy(dest,src,len);
+ return len;
+ }
+}
+
+/**
+ * Convert string from one encoding to another, making error checking etc
+ * Fast path version - handles ASCII first.
+ *
+ * @param src pointer to source string (multibyte or singlebyte)
+ * @param srclen length of the source string in bytes
+ * @param dest pointer to destination string (multibyte or singlebyte)
+ * @param destlen maximal length allowed for string
+ * @returns the number of bytes occupied in the destination
+ *
+ * Ensure the srclen contains the terminating zero.
+ *
+ * This function has been hand-tuned to provide a fast path.
+ * Don't change unless you really know what you are doing. JRA.
+ **/
+
+size_t convert_string(charset_t from, charset_t to,
+ void const *src, size_t srclen,
+ void *dest, size_t destlen)
+{
+ if (srclen == 0)
+ return 0;
+
+ if (from != CH_UCS2 && to != CH_UCS2) {
+ const unsigned char *p = (const unsigned char *)src;
+ unsigned char *q = (unsigned char *)dest;
+ unsigned char lastp;
+ size_t retval = 0;
+
+ /* If all characters are ascii, fast path here. */
+ while (srclen && destlen) {
+ if ((lastp = *p) <= 0x7f) {
+ *q++ = *p++;
+ if (srclen != (size_t)-1) {
+ srclen--;
+ }
+ destlen--;
+ retval++;
+ if (!lastp)
+ break;
+ } else {
+ if (srclen == (size_t)-1) {
+ srclen = strlen(p)+1;
+ }
+ return retval + convert_string_internal(from, to, p, srclen, q, destlen);
+ }
+ }
+ return retval;
+ } else if (from == CH_UCS2 && to != CH_UCS2) {
+ const unsigned char *p = (const unsigned char *)src;
+ unsigned char *q = (unsigned char *)dest;
+ size_t retval = 0;
+ unsigned char lastp;
+
+ /* If all characters are ascii, fast path here. */
+ while ((srclen >= 2) && destlen) {
+ if ((lastp = *p) <= 0x7f && p[1] == 0) {
+ *q++ = *p;
+ if (srclen != (size_t)-1) {
+ srclen -= 2;
+ }
+ p += 2;
+ destlen--;
+ retval++;
+ if (!lastp)
+ break;
+ } else {
+ if (srclen == (size_t)-1) {
+ srclen = strlen_w((const void *)p)+2;
+ }
+ return retval + convert_string_internal(from, to, p, srclen, q, destlen);
+ }
+ }
+ return retval;
+ } else if (from != CH_UCS2 && to == CH_UCS2) {
+ const unsigned char *p = (const unsigned char *)src;
+ unsigned char *q = (unsigned char *)dest;
+ size_t retval = 0;
+ unsigned char lastp;
+
+ /* If all characters are ascii, fast path here. */
+ while (srclen && (destlen >= 2)) {
+ if ((lastp = *p) <= 0x7F) {
+ *q++ = *p++;
+ *q++ = '\0';
+ if (srclen != (size_t)-1) {
+ srclen--;
+ }
+ destlen -= 2;
+ retval += 2;
+ if (!lastp)
+ break;
+ } else {
+ if (srclen == (size_t)-1) {
+ srclen = strlen(p)+1;
+ }
+ return retval + convert_string_internal(from, to, p, srclen, q, destlen);
+ }
+ }
+ return retval;
+ }
+ return convert_string_internal(from, to, src, srclen, dest, destlen);
}
/**
* Convert between character sets, allocating a new buffer for the result.
*
+ * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
* @param srclen length of source buffer.
* @param dest always set at least to NULL
* @note -1 is not accepted for srclen.
*
* @returns Size in bytes of the converted string; or -1 in case of error.
+ *
+ * Ensure the srclen contains the terminating zero.
**/
-size_t convert_string_allocate(charset_t from, charset_t to,
+size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
void const *src, size_t srclen, void **dest)
{
- size_t i_len, o_len, destlen;
+ size_t i_len, o_len, destlen = MAX(srclen, 512);
size_t retval;
const char *inbuf = (const char *)src;
- char *outbuf, *ob;
+ char *outbuf = NULL, *ob = NULL;
smb_iconv_t descriptor;
*dest = NULL;
if (src == NULL || srclen == (size_t)-1)
return (size_t)-1;
+ if (srclen == 0)
+ return 0;
lazy_initialize_conv();
descriptor = conv_handles[from][to];
if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
- /* conversion not supported, return -1*/
- DEBUG(3, ("convert_string_allocate: conversion not supported!\n"));
- return -1;
+ if (!conv_silent)
+ DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
+ goto use_as_is;
}
- destlen = MAX(srclen, 512);
- outbuf = NULL;
convert:
- destlen = destlen * 2;
- ob = (char *)Realloc(outbuf, destlen);
+ if ((destlen*2) < destlen) {
+ /* wrapped ! abort. */
+ if (!conv_silent)
+ DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
+ if (!ctx)
+ SAFE_FREE(outbuf);
+ return (size_t)-1;
+ } else {
+ destlen = destlen * 2;
+ }
+
+ if (ctx)
+ ob = (char *)talloc_realloc(ctx, ob, destlen);
+ else
+ ob = (char *)Realloc(ob, destlen);
+
if (!ob) {
DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
- SAFE_FREE(outbuf);
+ if (!ctx)
+ SAFE_FREE(outbuf);
return (size_t)-1;
} else {
outbuf = ob;
@@ -262,27 +406,59 @@ convert:
switch(errno) {
case EINVAL:
reason="Incomplete multibyte sequence";
- break;
+ if (!conv_silent)
+ DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
+ goto use_as_is;
case E2BIG:
goto convert;
case EILSEQ:
reason="Illegal multibyte sequence";
- break;
+ if (!conv_silent)
+ DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
+ goto use_as_is;
}
- DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
+ if (!conv_silent)
+ DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
/* smb_panic(reason); */
return (size_t)-1;
}
destlen = destlen - o_len;
- *dest = (char *)Realloc(ob,destlen);
+ if (ctx)
+ *dest = (char *)talloc_realloc(ctx,ob,destlen);
+ else
+ *dest = (char *)Realloc(ob,destlen);
if (destlen && !*dest) {
DEBUG(0, ("convert_string_allocate: out of memory!\n"));
- SAFE_FREE(ob);
+ if (!ctx)
+ SAFE_FREE(ob);
return (size_t)-1;
}
return destlen;
+
+ use_as_is:
+
+ /* conversion not supported, use as is */
+ {
+ if (srclen && (destlen != srclen)) {
+ destlen = srclen;
+ if (ctx)
+ ob = (char *)talloc_realloc(ctx, ob, destlen);
+ else
+ ob = (char *)Realloc(ob, destlen);
+ if (!ob) {
+ DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
+ if (!ctx)
+ SAFE_FREE(outbuf);
+ return (size_t)-1;
+ }
+ }
+ if (srclen && ob)
+ memcpy(ob,(const char *)src,srclen);
+ *dest = (char *)ob;
+ return srclen;
+ }
}
@@ -298,17 +474,12 @@ convert:
static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
void const *src, size_t srclen, void **dest)
{
- void *alloced_string;
size_t dest_len;
- /* FIXME: Ridiculous to allocate two buffers and then copy the string! */
-
*dest = NULL;
- dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string);
+ dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest);
if (dest_len == (size_t)-1)
return (size_t)-1;
- *dest = talloc_memdup(ctx, alloced_string, dest_len);
- SAFE_FREE(alloced_string);
if (*dest == NULL)
return (size_t)-1;
return dest_len;
@@ -335,29 +506,49 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
/**
strdup() a unix string to upper case.
+ Max size is pstring.
**/
char *strdup_upper(const char *s)
{
- size_t size;
- smb_ucs2_t *buffer;
- char *out_buffer;
-
- size = push_ucs2_allocate(&buffer, s);
- if (size == -1) {
- return NULL;
+ pstring out_buffer;
+ const unsigned char *p = (const unsigned char *)s;
+ unsigned char *q = (unsigned char *)out_buffer;
+
+ /* this is quite a common operation, so we want it to be
+ fast. We optimise for the ascii case, knowing that all our
+ supported multi-byte character sets are ascii-compatible
+ (ie. they match for the first 128 chars) */
+
+ while (1) {
+ if (*p & 0x80)
+ break;
+ *q++ = toupper(*p);
+ if (!*p)
+ break;
+ p++;
+ if (p - ( const unsigned char *)s >= sizeof(pstring))
+ break;
}
- strupper_w(buffer);
-
- size = pull_ucs2_allocate(&out_buffer, buffer);
- SAFE_FREE(buffer);
+ if (*p) {
+ /* MB case. */
+ size_t size;
+ wpstring buffer;
+ size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer));
+ if (size == -1) {
+ return NULL;
+ }
- if (size == -1) {
- return NULL;
- }
+ strupper_w(buffer);
- return out_buffer;
+ size = convert_string(CH_UCS2, CH_UNIX, buffer, sizeof(buffer), out_buffer, sizeof(out_buffer));
+ if (size == -1) {
+ return NULL;
+ }
+ }
+
+ return strdup(out_buffer);
}
size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
@@ -365,7 +556,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
size_t size;
smb_ucs2_t *buffer;
- size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen,
+ size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
(void **) &buffer);
if (size == -1) {
smb_panic("failed to create UCS2 buffer");
@@ -459,6 +650,11 @@ size_t push_ascii_pstring(void *dest, const char *src)
return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
}
+size_t push_ascii_nstring(void *dest, const char *src)
+{
+ return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE);
+}
+
/**
* Copy a string from a dos codepage source to a unix char* destination.
*
@@ -512,6 +708,11 @@ size_t pull_ascii_fstring(char *dest, const void *src)
return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
}
+size_t pull_ascii_nstring(char *dest, const void *src)
+{
+ return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE);
+}
+
/**
* Copy a string from a char* src to a unicode destination.
*
@@ -528,22 +729,26 @@ size_t pull_ascii_fstring(char *dest, const void *src)
* @param dest_len is the maximum length allowed in the
* destination. If dest_len is -1 then no maxiumum is used.
**/
+
size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
{
size_t len=0;
- size_t src_len = strlen(src);
+ size_t src_len;
/* treat a pstring as "unlimited" length */
if (dest_len == (size_t)-1)
dest_len = sizeof(pstring);
if (flags & STR_TERMINATE)
- src_len++;
+ src_len = (size_t)-1;
+ else
+ src_len = strlen(src);
if (ucs2_align(base_ptr, dest, flags)) {
*(char *)dest = 0;
dest = (void *)((char *)dest + 1);
- if (dest_len) dest_len--;
+ if (dest_len)
+ dest_len--;
len++;
}
@@ -599,7 +804,7 @@ size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
+ return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
}
/**
@@ -667,7 +872,7 @@ size_t push_utf8_allocate(char **dest, const char *src)
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
+ return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
}
/**
@@ -695,9 +900,8 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_
}
if (flags & STR_TERMINATE) {
- if (src_len == (size_t)-1) {
- src_len = strlen_w(src)*2 + 2;
- } else {
+ /* src_len -1 is the default for null terminated strings. */
+ if (src_len != (size_t)-1) {
size_t len = strnlen_w(src, src_len/2);
if (len < src_len/2)
len++;
@@ -755,7 +959,7 @@ size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
{
size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
*dest = NULL;
- return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
+ return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
}
/**
@@ -785,7 +989,7 @@ size_t pull_utf8_allocate(void **dest, const char *src)
{
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest);
+ return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, dest);
}
/**
@@ -845,8 +1049,10 @@ size_t push_string_fn(const char *function, unsigned int line, const void *base_
size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
{
+#ifdef DEVELOPER
if (dest_len != (size_t)-1)
clobber_region(function, line, dest, dest_len);
+#endif
if (!(flags & STR_ASCII) && \
((flags & STR_UNICODE || \
@@ -865,4 +1071,3 @@ size_t align_string(const void *base_ptr, const char *p, int flags)
}
return 0;
}
-
diff --git a/source3/lib/dummyroot.c b/source3/lib/dummyroot.c
new file mode 100644
index 0000000000..c8465cb791
--- /dev/null
+++ b/source3/lib/dummyroot.c
@@ -0,0 +1,33 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* Stupid dummy functions required due to the horrible dependency mess
+ in Samba. */
+
+void become_root(void)
+{
+ return;
+}
+
+void unbecome_root(void)
+{
+ return;
+}
diff --git a/source3/lib/fault.c b/source3/lib/fault.c
index a9e1b7bbb9..df7830ef83 100644
--- a/source3/lib/fault.c
+++ b/source3/lib/fault.c
@@ -34,7 +34,7 @@ static void fault_report(int sig)
counter++;
DEBUG(0,("===============================================================\n"));
- DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)sys_getpid(),VERSION));
+ DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)sys_getpid(),SAMBA_VERSION_STRING));
DEBUG(0,("\nPlease read the appendix Bugs of the Samba HOWTO collection\n"));
DEBUG(0,("===============================================================\n"));
diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c
index f3740e3e12..da8808af16 100644
--- a/source3/lib/gencache.c
+++ b/source3/lib/gencache.c
@@ -121,10 +121,11 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout)
keybuf.dsize = strlen(keystr)+1;
databuf.dptr = strdup(valstr);
databuf.dsize = strlen(valstr)+1;
- DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout \
- = %s (%d seconds %s)\n", keybuf.dptr, value, ctime(&timeout),
- (int)(timeout - time(NULL)), timeout > time(NULL) ? "ahead" : "in the past"));
-
+ DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout ="
+ " %s (%d seconds %s)\n", keybuf.dptr, value,ctime(&timeout),
+ (int)(timeout - time(NULL)),
+ timeout > time(NULL) ? "ahead" : "in the past"));
+
ret = tdb_store(cache, keybuf, databuf, 0);
SAFE_FREE(valstr);
SAFE_FREE(keybuf.dptr);
diff --git a/source3/lib/hash.c b/source3/lib/hash.c
index c7b1493b4c..18b6534dec 100644
--- a/source3/lib/hash.c
+++ b/source3/lib/hash.c
@@ -84,21 +84,20 @@ BOOL hash_table_init(hash_table *table, unsigned num_buckets, compare_function c
* For the last few chars that cannot be int'ed, use char instead.
* The function returns the bucket index number for the hashed
* key.
+ * JRA. Use a djb-algorithm hash for speed.
**************************************************************
*/
static int string_hash(int hash_size, const char *key)
{
- u32 value; /* Used to compute the hash value. */
- u32 i; /* Used to cycle through random values. */
-
- for (value = 0x238F13AF, i=0; key[i]; i++)
- value = (value + (key[i] << (i*5 % 24)));
-
- return (1103515243 * value + 12345) % hash_size;
+ u32 n = 0;
+ const char *p;
+ for (p = key; *p != '\0'; p++) {
+ n = ((n << 5) + n) ^ (u32)(*p);
+ }
+ return (n % hash_size);
}
-
/* *************************************************************************
* Search the hash table for the entry in the hash chain.
* The function returns the pointer to the
diff --git a/source3/lib/module.c b/source3/lib/module.c
index ac4fe57a2c..e2c6f6dcf5 100644
--- a/source3/lib/module.c
+++ b/source3/lib/module.c
@@ -23,7 +23,11 @@
#include "includes.h"
#ifdef HAVE_DLOPEN
-NTSTATUS smb_load_module(const char *module_name)
+
+/* Load a dynamic module. Only log a level 0 error if we are not checking
+ for the existence of a module (probling). */
+
+static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe)
{
void *handle;
init_module_function *init;
@@ -37,17 +41,21 @@ NTSTATUS smb_load_module(const char *module_name)
handle = sys_dlopen(module_name, RTLD_LAZY);
if(!handle) {
- DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror()));
+ int level = is_probe ? 2 : 0;
+ DEBUG(level, ("Error loading module '%s': %s\n", module_name,
+ sys_dlerror()));
+
return NT_STATUS_UNSUCCESSFUL;
}
- init = sys_dlsym(handle, "init_module");
+ init = (init_module_function *)sys_dlsym(handle, "init_module");
/* we must check sys_dlerror() to determine if it worked, because
sys_dlsym() can validly return NULL */
error = sys_dlerror();
if (error) {
- DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", module_name, error));
+ DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n",
+ module_name, error));
return NT_STATUS_UNSUCCESSFUL;
}
@@ -58,6 +66,11 @@ NTSTATUS smb_load_module(const char *module_name)
return status;
}
+NTSTATUS smb_load_module(const char *module_name)
+{
+ return do_smb_load_module(module_name, False);
+}
+
/* Load all modules in list and return number of
* modules that has been successfully loaded */
int smb_load_modules(const char **modules)
@@ -85,8 +98,11 @@ NTSTATUS smb_probe_module(const char *subsystem, const char *module)
/* if we make any 'samba multibyte string'
calls here, we break
for loading string modules */
+
+ DEBUG(5, ("Probing module '%s'\n", module));
+
if (module[0] == '/')
- return smb_load_module(module);
+ return do_smb_load_module(module, True);
pstrcpy(full_path, lib_path(subsystem));
pstrcat(full_path, "/");
@@ -94,9 +110,9 @@ NTSTATUS smb_probe_module(const char *subsystem, const char *module)
pstrcat(full_path, ".");
pstrcat(full_path, shlib_ext());
- DEBUG(5, ("Probing module %s: Trying to load from %s\n", module, full_path));
+ DEBUG(5, ("Probing module '%s': Trying to load from %s\n", module, full_path));
- return smb_load_module(full_path);
+ return do_smb_load_module(full_path, True);
}
#else /* HAVE_DLOPEN */
diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c
index 106efa5bbc..24232c3b52 100644
--- a/source3/lib/ms_fnmatch.c
+++ b/source3/lib/ms_fnmatch.c
@@ -35,7 +35,8 @@
of the protocol. This is not yet perfect, but its a lot
better than what we had */
static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern,
- const smb_ucs2_t *string)
+ const smb_ucs2_t *string,
+ BOOL case_sensitive)
{
const smb_ucs2_t *p = pattern, *n = string;
smb_ucs2_t c;
@@ -61,8 +62,8 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern,
case UCS2_CHAR('>'):
if (! *n) goto next;
if (n[0] == UCS2_CHAR('.')) {
- if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match;
- if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
+ if (! n[1] && ms_fnmatch_lanman_core(p, n+1, case_sensitive) == 0) goto match;
+ if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
goto nomatch;
}
n++;
@@ -72,13 +73,13 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern,
if (! *n) goto next;
if (! *p) goto match;
for (; *n; n++) {
- if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
+ if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
}
break;
case UCS2_CHAR('<'):
for (; *n; n++) {
- if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
+ if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
if (*n == UCS2_CHAR('.') &&
!strchr_w(n+1,UCS2_CHAR('.'))) {
n++;
@@ -88,13 +89,17 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern,
break;
case UCS2_CHAR('"'):
- if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match;
+ if (*n == 0 && ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
if (*n != UCS2_CHAR('.')) goto nomatch;
n++;
break;
default:
- if (c != *n) goto nomatch;
+ if (case_sensitive) {
+ if (c != *n) goto nomatch;
+ } else {
+ if (tolower_w(c) != tolower_w(*n)) goto nomatch;
+ }
n++;
}
}
@@ -108,7 +113,7 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern,
return -1;
next:
- if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
+ if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
goto nomatch;
match:
@@ -118,7 +123,8 @@ next:
return 0;
}
-static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *string)
+static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern,
+ const smb_ucs2_t *string, BOOL case_sensitive)
{
if (!strpbrk_wa(pattern, "?*<>\"")) {
smb_ucs2_t s[] = {UCS2_CHAR('.'), 0};
@@ -129,11 +135,11 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin
if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) {
smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0};
smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0};
- return ms_fnmatch_lanman_core(pattern, dotdot) &&
- ms_fnmatch_lanman_core(pattern, dot);
+ return ms_fnmatch_lanman_core(pattern, dotdot, case_sensitive) &&
+ ms_fnmatch_lanman_core(pattern, dot, case_sensitive);
}
- return ms_fnmatch_lanman_core(pattern, string);
+ return ms_fnmatch_lanman_core(pattern, string, case_sensitive);
}
@@ -145,13 +151,14 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin
Returns 0 on match, -1 on fail.
*/
-static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int protocol)
+static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string,
+ int protocol, BOOL case_sensitive)
{
const smb_ucs2_t *p = pattern, *n = string;
smb_ucs2_t c;
if (protocol <= PROTOCOL_LANMAN2) {
- return ms_fnmatch_lanman1(pattern, string);
+ return ms_fnmatch_lanman1(pattern, string, case_sensitive);
}
while ((c = *p++)) {
@@ -163,23 +170,23 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int
case UCS2_CHAR('>'):
if (n[0] == UCS2_CHAR('.')) {
- if (! n[1] && ms_fnmatch_w(p, n+1, protocol) == 0) return 0;
- if (ms_fnmatch_w(p, n, protocol) == 0) return 0;
+ if (! n[1] && ms_fnmatch_w(p, n+1, protocol, case_sensitive) == 0) return 0;
+ if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
return -1;
}
- if (! *n) return ms_fnmatch_w(p, n, protocol);
+ if (! *n) return ms_fnmatch_w(p, n, protocol, case_sensitive);
n++;
break;
case UCS2_CHAR('*'):
for (; *n; n++) {
- if (ms_fnmatch_w(p, n, protocol) == 0) return 0;
+ if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
}
break;
case UCS2_CHAR('<'):
for (; *n; n++) {
- if (ms_fnmatch_w(p, n, protocol) == 0) return 0;
+ if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) {
n++;
break;
@@ -188,13 +195,17 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int
break;
case UCS2_CHAR('"'):
- if (*n == 0 && ms_fnmatch_w(p, n, protocol) == 0) return 0;
+ if (*n == 0 && ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
if (*n != UCS2_CHAR('.')) return -1;
n++;
break;
default:
- if (c != *n) return -1;
+ if (case_sensitive) {
+ if (c != *n) return -1;
+ } else {
+ if (tolower_w(c) != tolower_w(*n)) return -1;
+ }
n++;
}
}
@@ -204,22 +215,35 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int
return -1;
}
-
-int ms_fnmatch(const char *pattern, const char *string, int protocol)
+int ms_fnmatch(const char *pattern, const char *string, int protocol,
+ BOOL case_senstive)
{
- wpstring p, s;
+ wpstring buffer_pattern, buffer_string;
int ret;
+ size_t size;
+
+ size = push_ucs2(NULL, buffer_pattern, pattern, sizeof(buffer_pattern), STR_TERMINATE);
+ if (size == (size_t)-1) {
+ return -1;
+ /* Not quite the right answer, but finding the right one
+ under this failure case is expensive, and it's pretty close */
+ }
+
+ size = push_ucs2(NULL, buffer_string, string, sizeof(buffer_string), STR_TERMINATE);
+ if (size == (size_t)-1) {
+ return -1;
+ /* Not quite the right answer, but finding the right one
+ under this failure case is expensive, and it's pretty close */
+ }
- pstrcpy_wa(p, pattern);
- pstrcpy_wa(s, string);
+ ret = ms_fnmatch_w(buffer_pattern, buffer_string, protocol, case_senstive);
+ DEBUG(10,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret));
- ret = ms_fnmatch_w(p, s, protocol);
-/* DEBUG(0,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); */
return ret;
}
/* a generic fnmatch function - uses for non-CIFS pattern matching */
int gen_fnmatch(const char *pattern, const char *string)
{
- return ms_fnmatch(pattern, string, PROTOCOL_NT1);
+ return ms_fnmatch(pattern, string, PROTOCOL_NT1, True);
}
diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c
index af1cbcfe80..9a5a112022 100644
--- a/source3/lib/popt_common.c
+++ b/source3/lib/popt_common.c
@@ -69,7 +69,7 @@ static void popt_common_callback(poptContext con,
break;
case 'V':
- printf( "Version %s\n", VERSION );
+ printf( "Version %s\n", SAMBA_VERSION_STRING);
exit(0);
break;
@@ -119,6 +119,7 @@ struct poptOption popt_common_connection[] = {
{ "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" },
{ "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" },
{ "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" },
+
POPT_TABLEEND
};
@@ -259,6 +260,7 @@ static void get_credentials_file(const char *file, struct user_auth_info *info)
* -k,--use-kerberos
* -N,--no-pass
* -S,--signing
+ * -P --machine-pass
*/
@@ -335,7 +337,8 @@ static void popt_common_credentials_callback(poptContext con,
cmdline_auth_info.signing_state = -1;
if (strequal(arg, "off") || strequal(arg, "no") || strequal(arg, "false"))
cmdline_auth_info.signing_state = False;
- else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true"))
+ else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true") ||
+ strequal(arg, "auto") )
cmdline_auth_info.signing_state = True;
else if (strequal(arg, "force") || strequal(arg, "required") || strequal(arg, "forced"))
cmdline_auth_info.signing_state = Required;
@@ -345,6 +348,33 @@ static void popt_common_credentials_callback(poptContext con,
}
}
break;
+ case 'P':
+ {
+ char *opt_password = NULL;
+ /* it is very useful to be able to make ads queries as the
+ machine account for testing purposes and for domain leave */
+
+ if (!secrets_init()) {
+ d_printf("ERROR: Unable to open secrets database\n");
+ exit(1);
+ }
+
+ opt_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+
+ if (!opt_password) {
+ d_printf("ERROR: Unable to fetch machine password\n");
+ exit(1);
+ }
+ pstr_sprintf(cmdline_auth_info.username, "%s$",
+ global_myname());
+ pstrcpy(cmdline_auth_info.password,opt_password);
+ SAFE_FREE(opt_password);
+
+ /* machine accounts only work with kerberos */
+ cmdline_auth_info.use_kerberos = True;
+ cmdline_auth_info.got_pass = True;
+ }
+ break;
}
}
@@ -357,5 +387,6 @@ struct poptOption popt_common_credentials[] = {
{ "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" },
{ "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" },
{ "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" },
+ {"machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" },
POPT_TABLEEND
};
diff --git a/source3/lib/readline.c b/source3/lib/readline.c
index ceb02ef749..78b99fd7fb 100644
--- a/source3/lib/readline.c
+++ b/source3/lib/readline.c
@@ -51,7 +51,7 @@
****************************************************************************/
static char *smb_readline_replacement(char *prompt, void (*callback)(void),
- char **(completion_fn)(char *text, int start, int end))
+ char **(completion_fn)(const char *text, int start, int end))
{
fd_set fds;
static pstring line;
@@ -83,7 +83,7 @@ static char *smb_readline_replacement(char *prompt, void (*callback)(void),
****************************************************************************/
char *smb_readline(char *prompt, void (*callback)(void),
- char **(completion_fn)(char *text, int start, int end))
+ char **(completion_fn)(const char *text, int start, int end))
{
#if HAVE_LIBREADLINE
if (isatty(x_fileno(x_stdin))) {
diff --git a/source3/lib/replace1.c b/source3/lib/replace1.c
new file mode 100644
index 0000000000..e1be56eb12
--- /dev/null
+++ b/source3/lib/replace1.c
@@ -0,0 +1,42 @@
+/*
+ Unix SMB/CIFS implementation.
+ replacement routines for broken systems
+ 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 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+ void replace1_dummy(void);
+ void replace1_dummy(void) {}
+
+#ifndef HAVE_SETENV
+ int setenv(const char *name, const char *value, int overwrite)
+{
+ char *p = NULL;
+ int ret = -1;
+
+ asprintf(&p, "%s=%s", name, value);
+
+ if (overwrite || getenv(name)) {
+ if (p) ret = putenv(p);
+ } else {
+ ret = 0;
+ }
+
+ return ret;
+}
+#endif
diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c
index 3f56d066ec..1ce03491da 100644
--- a/source3/lib/smbldap.c
+++ b/source3/lib/smbldap.c
@@ -1172,6 +1172,9 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
LDAPMessage *result = NULL;
int num_result;
char **attr_list;
+ uid_t u_low, u_high;
+ gid_t g_low, g_high;
+ uint32 rid_low, rid_high;
slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))",
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
@@ -1217,6 +1220,30 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
algorithmic_rid_base_string);
smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
+
+ /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set.
+ TODO: fix all the places where the line between idmap and normal operations
+ needed by smbd gets fuzzy --jerry 2003-08-11 */
+
+ if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high)
+ && get_free_rid_range(&rid_low, &rid_high) )
+ {
+ fstring rid_str;
+
+ fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE );
+ DEBUG(10,("setting next available user rid [%s]\n", rid_str));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
+ rid_str);
+
+ fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE );
+ DEBUG(10,("setting next available group rid [%s]\n", rid_str));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
+ rid_str);
+
+ }
+
switch(ldap_op)
{
diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c
index c0d0096806..28466e43f2 100644
--- a/source3/lib/substitute.c
+++ b/source3/lib/substitute.c
@@ -57,7 +57,7 @@ void set_local_machine_name(const char* local_name, BOOL perm)
already_perm = perm;
fstrcpy(tmp_local_machine,local_name);
- trim_string(tmp_local_machine," "," ");
+ trim_char(tmp_local_machine,' ',' ');
alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
strlower_m(local_machine);
}
@@ -79,7 +79,7 @@ void set_remote_machine_name(const char* remote_name, BOOL perm)
already_perm = perm;
fstrcpy(tmp_remote_machine,remote_name);
- trim_string(tmp_remote_machine," "," ");
+ trim_char(tmp_remote_machine,' ',' ');
alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
strlower_m(remote_machine);
}
@@ -98,23 +98,36 @@ const char* get_local_machine_name(void)
return local_machine;
}
+/*******************************************************************
+ Setup the string used by %U substitution.
+********************************************************************/
-/*
- setup the string used by %U substitution
-*/
void sub_set_smb_name(const char *name)
{
fstring tmp;
/* don't let anonymous logins override the name */
- if (! *name) return;
+ if (! *name)
+ return;
fstrcpy(tmp,name);
- trim_string(tmp," "," ");
+ trim_char(tmp,' ',' ');
strlower_m(tmp);
alpha_strcpy(smb_user_name,tmp,SAFE_NETBIOS_CHARS,sizeof(smb_user_name)-1);
}
+/*******************************************************************
+ Setup the strings used by substitutions. Called per packet. Ensure
+ %U name is set correctly also.
+********************************************************************/
+
+void set_current_user_info(const userdom_struct *pcui)
+{
+ current_user_info = *pcui;
+ /* The following is safe as current_user_info.smb_name
+ * has already been sanitised in register_vuid. */
+ fstrcpy(smb_user_name, current_user_info.smb_name);
+}
/*******************************************************************
Given a pointer to a %$(NAME) expand it as an environment variable.
@@ -384,7 +397,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len)
string_sub(p,"%m", get_remote_machine_name(),l);
break;
case 'v' :
- string_sub(p,"%v", VERSION,l);
+ string_sub(p,"%v", SAMBA_VERSION_STRING,l);
break;
case '$' :
p += expand_env_var(p,l);
@@ -539,7 +552,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
t = realloc_string_sub(t, "%m", remote_machine);
break;
case 'v' :
- t = realloc_string_sub(t, "%v", VERSION);
+ t = realloc_string_sub(t, "%v", SAMBA_VERSION_STRING);
break;
case '$' :
t = realloc_expand_env_var(t, p); /* Expand environment variables */
diff --git a/source3/lib/system.c b/source3/lib/system.c
index a7024c852d..b020a20373 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -1263,6 +1263,16 @@ ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t si
{
#if defined(HAVE_GETXATTR)
return getxattr(path, name, value, size);
+#elif defined(HAVE_ATTR_GET)
+ int retval, flags = 0;
+ int valuelength = (int)size;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
+
+ return retval ? retval : valuelength;
#else
errno = ENOSYS;
return -1;
@@ -1273,6 +1283,16 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s
{
#if defined(HAVE_LGETXATTR)
return lgetxattr(path, name, value, size);
+#elif defined(HAVE_ATTR_GET)
+ int retval, flags = ATTR_DONTFOLLOW;
+ int valuelength = (int)size;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
+
+ return retval ? retval : valuelength;
#else
errno = ENOSYS;
return -1;
@@ -1283,16 +1303,96 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
{
#if defined(HAVE_FGETXATTR)
return fgetxattr(filedes, name, value, size);
+#elif defined(HAVE_ATTR_GETF)
+ int retval, flags = 0;
+ int valuelength = (int)size;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
+
+ return retval ? retval : valuelength;
#else
errno = ENOSYS;
return -1;
#endif
}
+#if defined(HAVE_ATTR_LIST)
+static char attr_buffer[ATTR_MAX_VALUELEN];
+
+static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
+{
+ int retval = 0, index;
+ attrlist_cursor_t *cursor = 0;
+ int total_size = 0;
+ attrlist_t * al = (attrlist_t *)attr_buffer;
+ attrlist_ent_t *ae;
+ size_t ent_size, left = size;
+ char *bp = list;
+
+ while (True) {
+ if (filedes)
+ retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
+ else
+ retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
+ if (retval) break;
+ for (index = 0; index < al->al_count; index++) {
+ ae = ATTR_ENTRY(attr_buffer, index);
+ ent_size = strlen(ae->a_name) + sizeof("user.");
+ if (left >= ent_size) {
+ strncpy(bp, "user.", sizeof("user."));
+ strncat(bp, ae->a_name, ent_size - sizeof("user."));
+ bp += ent_size;
+ left -= ent_size;
+ } else if (size) {
+ errno = ERANGE;
+ retval = -1;
+ break;
+ }
+ total_size += ent_size;
+ }
+ if (al->al_more == 0) break;
+ }
+ if (retval == 0) {
+ flags |= ATTR_ROOT;
+ cursor = 0;
+ while (True) {
+ if (filedes)
+ retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
+ else
+ retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
+ if (retval) break;
+ for (index = 0; index < al->al_count; index++) {
+ ae = ATTR_ENTRY(attr_buffer, index);
+ ent_size = strlen(ae->a_name) + sizeof("system.");
+ if (left >= ent_size) {
+ strncpy(bp, "system.", sizeof("system."));
+ strncat(bp, ae->a_name, ent_size - sizeof("system."));
+ bp += ent_size;
+ left -= ent_size;
+ } else if (size) {
+ errno = ERANGE;
+ retval = -1;
+ break;
+ }
+ total_size += ent_size;
+ }
+ if (al->al_more == 0) break;
+ }
+ }
+ return (ssize_t)(retval ? retval : total_size);
+}
+
+#endif
+
ssize_t sys_listxattr (const char *path, char *list, size_t size)
{
#if defined(HAVE_LISTXATTR)
return listxattr(path, list, size);
+#elif defined(HAVE_ATTR_LIST)
+ return irix_attr_list(path, 0, list, size, 0);
#else
errno = ENOSYS;
return -1;
@@ -1301,8 +1401,10 @@ ssize_t sys_listxattr (const char *path, char *list, size_t size)
ssize_t sys_llistxattr (const char *path, char *list, size_t size)
{
-#if defined(HAVE_GETXATTR)
+#if defined(HAVE_LLISTXATTR)
return llistxattr(path, list, size);
+#elif defined(HAVE_ATTR_LIST)
+ return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
#else
errno = ENOSYS;
return -1;
@@ -1313,6 +1415,8 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size)
{
#if defined(HAVE_FLISTXATTR)
return flistxattr(filedes, list, size);
+#elif defined(HAVE_ATTR_LISTF)
+ return irix_attr_list(NULL, filedes, list, size, 0);
#else
errno = ENOSYS;
return -1;
@@ -1323,6 +1427,13 @@ int sys_removexattr (const char *path, const char *name)
{
#if defined(HAVE_REMOVEXATTR)
return removexattr(path, name);
+#elif defined(HAVE_ATTR_REMOVE)
+ int flags = 0;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ return attr_remove(path, attrname, flags);
#else
errno = ENOSYS;
return -1;
@@ -1333,6 +1444,13 @@ int sys_lremovexattr (const char *path, const char *name)
{
#if defined(HAVE_LREMOVEXATTR)
return lremovexattr(path, name);
+#elif defined(HAVE_ATTR_REMOVE)
+ int flags = ATTR_DONTFOLLOW;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ return attr_remove(path, attrname, flags);
#else
errno = ENOSYS;
return -1;
@@ -1343,16 +1461,37 @@ int sys_fremovexattr (int filedes, const char *name)
{
#if defined(HAVE_FREMOVEXATTR)
return fremovexattr(filedes, name);
+#elif defined(HAVE_ATTR_REMOVEF)
+ int flags = 0;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ return attr_removef(filedes, attrname, flags);
#else
errno = ENOSYS;
return -1;
#endif
}
+#if !defined(HAVE_SETXATTR)
+#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
+#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
+#endif
+
int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
{
#if defined(HAVE_SETXATTR)
return setxattr(path, name, value, size, flags);
+#elif defined(HAVE_ATTR_SET)
+ int myflags = 0;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
+ if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
+ if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
+
+ return attr_set(path, attrname, (const char *)value, size, myflags);
#else
errno = ENOSYS;
return -1;
@@ -1363,6 +1502,15 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t
{
#if defined(HAVE_LSETXATTR)
return lsetxattr(path, name, value, size, flags);
+#elif defined(HAVE_ATTR_SET)
+ int myflags = ATTR_DONTFOLLOW;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
+ if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
+ if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
+
+ return attr_set(path, attrname, (const char *)value, size, myflags);
#else
errno = ENOSYS;
return -1;
@@ -1373,6 +1521,15 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size
{
#if defined(HAVE_FSETXATTR)
return fsetxattr(filedes, name, value, size, flags);
+#elif defined(HAVE_ATTR_SETF)
+ int myflags = 0;
+ char *attrname = strchr(name,'.') +1;
+
+ if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
+ if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
+ if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
+
+ return attr_setf(filedes, attrname, (const char *)value, size, myflags);
#else
errno = ENOSYS;
return -1;
diff --git a/source3/lib/util.c b/source3/lib/util.c
index eaa232a549..766c5041b4 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -261,7 +261,7 @@ BOOL init_names(void)
}
fstrcpy( local_machine, global_myname() );
- trim_string( local_machine, " ", " " );
+ trim_char( local_machine, ' ', ' ' );
p = strchr( local_machine, ' ' );
if (p)
*p = 0;
@@ -311,7 +311,7 @@ BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups)
static const char *Atoic(const char *p, int *n, const char *c)
{
- if (!isdigit((const int)*p)) {
+ if (!isdigit((int)*p)) {
DEBUG(5, ("Atoic: malformed number\n"));
return NULL;
}
@@ -605,68 +605,6 @@ void unix_clean_name(char *s)
trim_string(s,NULL,"/..");
}
-/*******************************************************************
- Convert '\' to '/'.
- Reduce a file name, removing or reducing /../ , /./ , // elements.
- Remove also any trailing . and /
- Return a new allocated string.
-********************************************************************/
-
-smb_ucs2_t *unix_clean_path(const smb_ucs2_t *s)
-{
- smb_ucs2_t *ns;
- smb_ucs2_t *p, *r, *t;
-
- DEBUG(3, ("unix_clean_path\n")); /* [%unicode]\n")); */
- if(!s)
- return NULL;
-
- /* convert '\' to '/' */
- ns = strdup_w(s);
- if (!ns)
- return NULL;
- unix_format_w(ns);
-
- /* remove all double slashes */
- p = ns;
- ns = all_string_sub_wa(p, "//", "/");
- SAFE_FREE(p);
- if (!ns)
- return NULL;
-
- /* remove any /./ */
- p = ns;
- ns = all_string_sub_wa(p, "/./", "/");
- SAFE_FREE(p);
- if (!ns)
- return NULL;
-
- /* reduce any /../ */
- t = ns;
- while (*t && (r = strstr_wa(t, "/.."))) {
- t = &(r[3]);
- if (*t == UCS2_CHAR('/') || *t == 0) {
- *r = 0;
- p = strrchr_w(ns, UCS2_CHAR('/'));
- if (!p)
- p = ns;
- if (*t == 0)
- *p = 0;
- else
- memmove(p, t, (strlen_w(t) + 1) * sizeof(smb_ucs2_t));
- t = p;
- }
- }
-
- /* remove any leading ./ trailing /. */
- trim_string_wa(ns, "./", "/.");
-
- /* remove any leading and trailing / */
- trim_string_wa(ns, "/", "/");
-
- return ns;
-}
-
/****************************************************************************
Make a dir struct.
****************************************************************************/
@@ -2205,7 +2143,7 @@ char *lock_path(const char *name)
static pstring fname;
pstrcpy(fname,lp_lockdir());
- trim_string(fname,"","/");
+ trim_char(fname,'\0','/');
if (!directory_exist(fname,NULL))
mkdir(fname,0755);
@@ -2225,7 +2163,7 @@ char *pid_path(const char *name)
static pstring fname;
pstrcpy(fname,lp_piddir());
- trim_string(fname,"","/");
+ trim_char(fname,'\0','/');
if (!directory_exist(fname,NULL))
mkdir(fname,0755);
@@ -2335,21 +2273,12 @@ BOOL ms_has_wild_w(const smb_ucs2_t *s)
BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive)
{
- fstring p2, s2;
-
if (strcmp(string,"..") == 0)
string = ".";
if (strcmp(pattern,".") == 0)
return False;
- if (is_case_sensitive)
- return ms_fnmatch(pattern, string, Protocol) == 0;
-
- fstrcpy(p2, pattern);
- fstrcpy(s2, string);
- strlower_m(p2);
- strlower_m(s2);
- return ms_fnmatch(p2, s2, Protocol) == 0;
+ return ms_fnmatch(pattern, string, Protocol, is_case_sensitive) == 0;
}
/*********************************************************
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index 638a6ca342..bd505ac921 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -20,6 +20,11 @@
#include "includes.h"
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+
static int gotalarm;
/***************************************************************
diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c
index 00f14d7d26..fbb393770d 100644
--- a/source3/lib/util_sid.c
+++ b/source3/lib/util_sid.c
@@ -93,7 +93,7 @@ static const struct {
{SID_NAME_UNKNOWN, "UNKNOWN"},
{SID_NAME_COMPUTER, "Computer"},
- {0, NULL}
+ {(enum SID_NAME_USE)0, NULL}
};
const char *sid_type_lookup(uint32 sid_type)
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index 7569a39e6a..82b312e241 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -37,7 +37,7 @@
**/
BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
{
- const char *s;
+ char *s;
char *pbuf;
BOOL quoted;
size_t len=1;
@@ -45,7 +45,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
if (!ptr)
return(False);
- s = *ptr;
+ s = (char *)*ptr;
/* default to simple separators */
if (!sep)
@@ -88,7 +88,7 @@ BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
{
BOOL ret;
if (!ptr)
- ptr = (const char **)&last_ptr;
+ ptr = &last_ptr;
ret = next_token(ptr, buff, sep, bufsize);
last_ptr = *ptr;
@@ -109,7 +109,7 @@ void set_first_token(char *ptr)
char **toktocliplist(int *ctok, const char *sep)
{
- char *s=last_ptr;
+ char *s=(char *)last_ptr;
int ictok=0;
char **ret, **iret;
@@ -132,7 +132,7 @@ char **toktocliplist(int *ctok, const char *sep)
} while(*s);
*ctok=ictok;
- s=last_ptr;
+ s=(char *)last_ptr;
if (!(ret=iret=malloc(ictok*sizeof(char *))))
return NULL;
@@ -364,9 +364,27 @@ BOOL strisnormal(const char *s)
void string_replace(pstring s,char oldc,char newc)
{
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
+ unsigned char *p;
+
+ /* this is quite a common operation, so we want it to be
+ fast. We optimise for the ascii case, knowing that all our
+ supported multi-byte character sets are ascii-compatible
+ (ie. they match for the first 128 chars) */
+
+ for (p = (unsigned char *)s; *p; p++) {
+ if (*p & 0x80) /* mb string - slow path. */
+ break;
+ if (*p == oldc)
+ *p = newc;
+ }
+
+ if (!*p)
+ return;
+
+ /* Slow (mb) path. */
+ push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE);
string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
- pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
+ pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
}
/**
@@ -406,6 +424,59 @@ size_t str_ascii_charnum(const char *s)
return strlen(tmpbuf2);
}
+BOOL trim_char(char *s,char cfront,char cback)
+{
+ BOOL ret = False;
+ char *ep;
+ char *fp = s;
+
+ /* Ignore null or empty strings. */
+ if (!s || (s[0] == '\0'))
+ return False;
+
+ if (cfront) {
+ while (*fp && *fp == cfront)
+ fp++;
+ if (!*fp) {
+ /* We ate the string. */
+ s[0] = '\0';
+ return True;
+ }
+ if (fp != s)
+ ret = True;
+ }
+
+ ep = fp + strlen(fp) - 1;
+ if (cback) {
+ /* Attempt ascii only. Bail for mb strings. */
+ while ((ep >= fp) && (*ep == cback)) {
+ ret = True;
+ if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
+ /* Could be mb... bail back to tim_string. */
+ char fs[2], bs[2];
+ if (cfront) {
+ fs[0] = cfront;
+ fs[1] = '\0';
+ }
+ bs[0] = cback;
+ bs[1] = '\0';
+ return trim_string(s, cfront ? fs : NULL, bs);
+ } else {
+ ep--;
+ }
+ }
+ if (ep < fp) {
+ /* We ate the string. */
+ s[0] = '\0';
+ return True;
+ }
+ }
+
+ ep[1] = '\0';
+ memmove(s, fp, ep-fp+2);
+ return ret;
+}
+
/**
Trim the specified elements off the front and back of a string.
**/
@@ -428,7 +499,9 @@ BOOL trim_string(char *s,const char *front,const char *back)
if (front_len) {
while (len && strncmp(s, front, front_len)==0) {
- memcpy(s, s+front_len, (len-front_len)+1);
+ /* Must use memmove here as src & dest can
+ * easily overlap. Found by valgrind. JRA. */
+ memmove(s, s+front_len, (len-front_len)+1);
len -= front_len;
ret=True;
}
@@ -501,7 +574,9 @@ char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_
return NULL;
}
+#ifdef DEVELOPER
clobber_region(fn,line,dest, maxlength+1);
+#endif
if (!src) {
*dest = 0;
@@ -540,7 +615,9 @@ char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size
src_len = strnlen(src, maxlength + 1);
dest_len = strnlen(dest, maxlength + 1);
+#ifdef DEVELOPER
clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
+#endif
if (src_len + dest_len > maxlength) {
DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
@@ -567,7 +644,9 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con
{
size_t len, i;
+#ifdef DEVELOPER
clobber_region(fn, line, dest, maxlength);
+#endif
if (!dest) {
DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
@@ -607,7 +686,9 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
{
char *d = dest;
+#ifdef DEVELOPER
clobber_region(fn, line, dest, n+1);
+#endif
if (!dest)
return(NULL);
@@ -637,8 +718,9 @@ static char *strncpyn(char *dest, const char *src, size_t n, char c)
char *p;
size_t str_len;
+#ifdef DEVELOPER
clobber_region(dest, n+1);
-
+#endif
p = strchr_m(src, c);
if (p == NULL) {
DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
@@ -910,6 +992,7 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert)
while ((p = strstr(s,pattern))) {
if (ld > 0) {
+ int offset = PTR_DIFF(s,string);
char *t = Realloc(string, ls + ld + 1);
if (!t) {
DEBUG(0, ("realloc_string_sub: out of memory!\n"));
@@ -917,7 +1000,7 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert)
return NULL;
}
string = t;
- p = t + (p - s);
+ p = t + offset + (p - s);
}
if (li != lp) {
memmove(p+li,p+lp,strlen(p+lp)+1);
@@ -1098,6 +1181,19 @@ char *strchr_m(const char *s, char c)
pstring s2;
smb_ucs2_t *p;
+ /* this is quite a common operation, so we want it to be
+ fast. We optimise for the ascii case, knowing that all our
+ supported multi-byte character sets are ascii-compatible
+ (ie. they match for the first 128 chars) */
+
+ while (*s && (((unsigned char)s[0]) & 0x80)) {
+ if (*s == c)
+ return s;
+ }
+
+ if (!*s)
+ return NULL;
+
push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
p = strchr_w(ws, UCS2_CHAR(c));
if (!p)
@@ -1109,17 +1205,53 @@ char *strchr_m(const char *s, char c)
char *strrchr_m(const char *s, char c)
{
- wpstring ws;
- pstring s2;
- smb_ucs2_t *p;
+ /* this is quite a common operation, so we want it to be
+ fast. We optimise for the ascii case, knowing that all our
+ supported multi-byte character sets are ascii-compatible
+ (ie. they match for the first 128 chars). Also, in Samba
+ we only search for ascii characters in 'c' and that
+ in all mb character sets with a compound character
+ containing c, if 'c' is not a match at position
+ p, then p[-1] > 0x7f. JRA. */
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
- p = strrchr_w(ws, UCS2_CHAR(c));
- if (!p)
- return NULL;
- *p = 0;
- pull_ucs2_pstring(s2, ws);
- return (char *)(s+strlen(s2));
+ {
+ size_t len = strlen(s);
+ const char *cp = s;
+ BOOL got_mb = False;
+
+ if (len == 0)
+ return NULL;
+ cp += (len - 1);
+ do {
+ if (c == *cp) {
+ /* Could be a match. Part of a multibyte ? */
+ if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
+ /* Yep - go slow :-( */
+ got_mb = True;
+ break;
+ }
+ /* No - we have a match ! */
+ return cp;
+ }
+ } while (cp-- != s);
+ if (!got_mb)
+ return NULL;
+ }
+
+ /* String contained a non-ascii char. Slow path. */
+ {
+ wpstring ws;
+ pstring s2;
+ smb_ucs2_t *p;
+
+ push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
+ p = strrchr_w(ws, UCS2_CHAR(c));
+ if (!p)
+ return NULL;
+ *p = 0;
+ pull_ucs2_pstring(s2, ws);
+ return (char *)(s+strlen(s2));
+ }
}
/***********************************************************************
@@ -1409,6 +1541,35 @@ void str_list_free(char ***list)
SAFE_FREE(*list);
}
+/******************************************************************************
+ version of standard_sub_basic() for string lists; uses alloc_sub_basic()
+ for the work
+ *****************************************************************************/
+
+BOOL str_list_sub_basic( char **list, const char *smb_name )
+{
+ char *s, *tmpstr;
+
+ while ( *list ) {
+ s = *list;
+ tmpstr = alloc_sub_basic(smb_name, s);
+ if ( !tmpstr ) {
+ DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
+ return False;
+ }
+
+ *list = tmpstr;
+
+ list++;
+ }
+
+ return True;
+}
+
+/******************************************************************************
+ substritute a specific pattern in a string list
+ *****************************************************************************/
+
BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
{
char *p, *s, *t;
@@ -1464,6 +1625,7 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
}
}
+
list++;
}
diff --git a/source3/lib/version.c b/source3/lib/version.c
new file mode 100644
index 0000000000..99f836c2d5
--- /dev/null
+++ b/source3/lib/version.c
@@ -0,0 +1,42 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba Version functions
+
+ Copyright (C) Stefan Metzmacher 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+const char *samba_version_string(void)
+{
+#ifndef SAMBA_VERSION_VENDOR_SUFFIX
+ return SAMBA_VERSION_OFFICIAL_STRING;
+#else
+ static fstring samba_version;
+ static BOOL init_samba_version;
+
+ if (init_samba_version)
+ return samba_version;
+
+ snprintf(samba_version,sizeof(samba_version),"%s-%s",
+ SAMBA_VERSION_OFFICIAL_STRING,
+ SAMBA_VERSION_VENDOR_SUFFIX);
+
+ init_samba_version = True;
+ return samba_version;
+#endif
+}