summaryrefslogtreecommitdiffstats
path: root/source3/smbd/srvstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/srvstr.c')
-rw-r--r--source3/smbd/srvstr.c57
1 files changed, 49 insertions, 8 deletions
diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c
index 648c69fbb7..e6a85419b8 100644
--- a/source3/smbd/srvstr.c
+++ b/source3/smbd/srvstr.c
@@ -24,16 +24,56 @@
/* Make sure we can't write a string past the end of the buffer */
-size_t srvstr_push_fn(const char *base_ptr, uint16 smb_flags2, void *dest,
- const char *src, int dest_len, int flags)
+NTSTATUS srvstr_push_fn(const char *base_ptr, uint16 smb_flags2, void *dest,
+ const char *src, int dest_len, int flags, size_t *ret_len)
{
+ size_t len;
+ int saved_errno;
+ NTSTATUS status;
+
if (dest_len < 0) {
- return 0;
+ return NT_STATUS_INVALID_PARAMETER;
}
+ saved_errno = errno;
+ errno = 0;
+
/* 'normal' push into size-specified buffer */
- return push_string_base(base_ptr, smb_flags2, dest, src,
+ len = push_string_base(base_ptr, smb_flags2, dest, src,
dest_len, flags);
+
+ if (errno != 0) {
+ /*
+ * Special case E2BIG, EILSEQ, EINVAL
+ * as they mean conversion errors here,
+ * but we don't generically map them as
+ * they can mean different things in
+ * generic filesystem calls (such as
+ * read xattrs).
+ */
+ if (errno == E2BIG || errno == EILSEQ || errno == EINVAL) {
+ status = NT_STATUS_ILLEGAL_CHARACTER;
+ } else {
+ status = map_nt_error_from_unix_common(errno);
+ /*
+ * Paranoia - Filter out STATUS_MORE_ENTRIES.
+ * I don't think we can get this but it has a
+ * specific meaning to the client.
+ */
+ if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ DEBUG(10,("character conversion failure "
+ "on string (%s) (%s)\n",
+ src, strerror(errno)));
+ } else {
+ /* Success - restore untouched errno. */
+ errno = saved_errno;
+ *ret_len = len;
+ status = NT_STATUS_OK;
+ }
+ return status;
}
/*******************************************************************
@@ -45,8 +85,9 @@ ssize_t message_push_string(uint8 **outbuf, const char *str, int flags)
{
size_t buf_size = smb_len(*outbuf) + 4;
size_t grow_size;
- size_t result;
+ size_t result = 0;
uint8 *tmp;
+ NTSTATUS status;
/*
* We need to over-allocate, now knowing what srvstr_push will
@@ -62,10 +103,10 @@ ssize_t message_push_string(uint8 **outbuf, const char *str, int flags)
return -1;
}
- result = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
- tmp + buf_size, str, grow_size, flags);
+ status = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
+ tmp + buf_size, str, grow_size, flags, &result);
- if (result == 0) {
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("srvstr_push failed\n"));
return -1;
}