diff options
Diffstat (limited to 'source3/smbd/srvstr.c')
-rw-r--r-- | source3/smbd/srvstr.c | 57 |
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; } |