Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : server specific string routines
4 : Copyright (C) Andrew Tridgell 2001
5 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "smbd/smbd.h"
23 : #include "smbd/globals.h"
24 : #include "lib/util/string_wrappers.h"
25 :
26 : /* Make sure we can't write a string past the end of the buffer */
27 :
28 608577 : NTSTATUS srvstr_push_fn(const char *base_ptr, uint16_t smb_flags2, void *dest,
29 : const char *src, int dest_len, int flags, size_t *ret_len)
30 : {
31 : size_t len;
32 : int saved_errno;
33 : NTSTATUS status;
34 :
35 608577 : if (dest_len < 0) {
36 0 : return NT_STATUS_INVALID_PARAMETER;
37 : }
38 :
39 608577 : saved_errno = errno;
40 608577 : errno = 0;
41 :
42 : /* 'normal' push into size-specified buffer */
43 608577 : len = push_string_base(base_ptr, smb_flags2, dest, src,
44 : dest_len, flags);
45 :
46 608577 : if (errno != 0) {
47 : /*
48 : * Special case E2BIG, EILSEQ, EINVAL
49 : * as they mean conversion errors here,
50 : * but we don't generically map them as
51 : * they can mean different things in
52 : * generic filesystem calls (such as
53 : * read xattrs).
54 : */
55 40 : if (errno == E2BIG || errno == EILSEQ || errno == EINVAL) {
56 40 : status = NT_STATUS_ILLEGAL_CHARACTER;
57 : } else {
58 0 : status = map_nt_error_from_unix_common(errno);
59 : /*
60 : * Paranoia - Filter out STATUS_MORE_ENTRIES.
61 : * I don't think we can get this but it has a
62 : * specific meaning to the client.
63 : */
64 0 : if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
65 0 : status = NT_STATUS_UNSUCCESSFUL;
66 : }
67 : }
68 40 : DEBUG(10,("character conversion failure "
69 : "on string (%s) (%s)\n",
70 : src, strerror(errno)));
71 : } else {
72 : /* Success - restore untouched errno. */
73 608537 : errno = saved_errno;
74 608537 : *ret_len = len;
75 608537 : status = NT_STATUS_OK;
76 : }
77 608577 : return status;
78 : }
79 :
80 : /*******************************************************************
81 : Add a string to the end of a smb_buf, adjusting bcc and smb_len.
82 : Return the bytes added
83 : ********************************************************************/
84 :
85 44447 : ssize_t message_push_string(uint8_t **outbuf, const char *str, int flags)
86 : {
87 44447 : size_t buf_size = smb_len(*outbuf) + 4;
88 : size_t grow_size;
89 44447 : size_t result = 0;
90 : uint8_t *tmp;
91 : NTSTATUS status;
92 :
93 : /*
94 : * We need to over-allocate, now knowing what srvstr_push will
95 : * actually use. This is very generous by incorporating potential
96 : * padding, the terminating 0 and at most 4 chars per UTF-16 code
97 : * point.
98 : */
99 44447 : grow_size = (strlen(str) + 2) * 4;
100 :
101 44447 : if (!(tmp = talloc_realloc(NULL, *outbuf, uint8_t,
102 : buf_size + grow_size))) {
103 0 : DEBUG(0, ("talloc failed\n"));
104 0 : return -1;
105 : }
106 :
107 44447 : status = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
108 : tmp + buf_size, str, grow_size, flags, &result);
109 :
110 44447 : if (!NT_STATUS_IS_OK(status)) {
111 0 : DEBUG(0, ("srvstr_push failed\n"));
112 0 : return -1;
113 : }
114 :
115 : /*
116 : * Ensure we clear out the extra data we have
117 : * grown the buffer by, but not written to.
118 : */
119 44447 : if (buf_size + result < buf_size) {
120 0 : return -1;
121 : }
122 44447 : if (grow_size < result) {
123 0 : return -1;
124 : }
125 :
126 45119 : memset(tmp + buf_size + result, '\0', grow_size - result);
127 :
128 44447 : set_message_bcc((char *)tmp, smb_buflen(tmp) + result);
129 :
130 44447 : *outbuf = tmp;
131 :
132 44447 : return result;
133 : }
|