2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2002
6 Copyright (C) James Myers 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/smb/smb_common.h"
24 #include "system/filesys.h"
26 const char *smb_protocol_types_string(enum protocol_types protocol
)
29 case PROTOCOL_DEFAULT
:
35 case PROTOCOL_COREPLUS
:
37 case PROTOCOL_LANMAN1
:
39 case PROTOCOL_LANMAN2
:
43 case PROTOCOL_SMB2_02
:
45 case PROTOCOL_SMB2_10
:
47 case PROTOCOL_SMB2_22
:
49 case PROTOCOL_SMB2_24
:
51 case PROTOCOL_SMB3_00
:
53 case PROTOCOL_SMB3_02
:
55 case PROTOCOL_SMB3_10
:
57 case PROTOCOL_SMB3_11
:
61 return "Invalid protocol_types value";
65 Return a string representing a CIFS attribute for a file.
67 char *attrib_string(TALLOC_CTX
*mem_ctx
, uint32_t attrib
)
74 {'V', FILE_ATTRIBUTE_VOLUME
},
75 {'D', FILE_ATTRIBUTE_DIRECTORY
},
76 {'A', FILE_ATTRIBUTE_ARCHIVE
},
77 {'H', FILE_ATTRIBUTE_HIDDEN
},
78 {'S', FILE_ATTRIBUTE_SYSTEM
},
79 {'N', FILE_ATTRIBUTE_NORMAL
},
80 {'R', FILE_ATTRIBUTE_READONLY
},
81 {'d', FILE_ATTRIBUTE_DEVICE
},
82 {'t', FILE_ATTRIBUTE_TEMPORARY
},
83 {'s', FILE_ATTRIBUTE_SPARSE
},
84 {'r', FILE_ATTRIBUTE_REPARSE_POINT
},
85 {'c', FILE_ATTRIBUTE_COMPRESSED
},
86 {'o', FILE_ATTRIBUTE_OFFLINE
},
87 {'n', FILE_ATTRIBUTE_NONINDEXED
},
88 {'e', FILE_ATTRIBUTE_ENCRYPTED
}
92 ret
= talloc_array(mem_ctx
, char, ARRAY_SIZE(attr_strs
)+1);
97 for (len
=i
=0; i
<ARRAY_SIZE(attr_strs
); i
++) {
98 if (attrib
& attr_strs
[i
].attr
) {
99 ret
[len
++] = attr_strs
[i
].c
;
105 talloc_set_name_const(ret
, ret
);
110 /****************************************************************************
111 Map standard UNIX permissions onto wire representations.
112 ****************************************************************************/
114 uint32_t unix_perms_to_wire(mode_t perms
)
116 unsigned int ret
= 0;
118 ret
|= ((perms
& S_IXOTH
) ? UNIX_X_OTH
: 0);
119 ret
|= ((perms
& S_IWOTH
) ? UNIX_W_OTH
: 0);
120 ret
|= ((perms
& S_IROTH
) ? UNIX_R_OTH
: 0);
121 ret
|= ((perms
& S_IXGRP
) ? UNIX_X_GRP
: 0);
122 ret
|= ((perms
& S_IWGRP
) ? UNIX_W_GRP
: 0);
123 ret
|= ((perms
& S_IRGRP
) ? UNIX_R_GRP
: 0);
124 ret
|= ((perms
& S_IXUSR
) ? UNIX_X_USR
: 0);
125 ret
|= ((perms
& S_IWUSR
) ? UNIX_W_USR
: 0);
126 ret
|= ((perms
& S_IRUSR
) ? UNIX_R_USR
: 0);
128 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
131 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
134 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
139 /****************************************************************************
140 Map wire permissions to standard UNIX.
141 ****************************************************************************/
143 mode_t
wire_perms_to_unix(uint32_t perms
)
145 mode_t ret
= (mode_t
)0;
147 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
148 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
149 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
150 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
151 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
152 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
153 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
154 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
155 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
157 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
160 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
163 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
168 /****************************************************************************
169 Return the file type from the wire filetype for UNIX extensions.
170 ****************************************************************************/
172 mode_t
unix_filetype_from_wire(uint32_t wire_type
)
180 case UNIX_TYPE_SYMLINK
:
184 case UNIX_TYPE_CHARDEV
:
188 case UNIX_TYPE_BLKDEV
:
196 case UNIX_TYPE_SOCKET
:
204 bool smb_buffer_oob(uint32_t bufsize
, uint32_t offset
, uint32_t length
)
206 if ((offset
+ length
< offset
) || (offset
+ length
< length
)) {
210 if ((offset
> bufsize
) || (offset
+ length
> bufsize
)) {
217 /***********************************************************
218 Common function for pushing stings, used by smb_bytes_push_str()
219 and trans_bytes_push_str(). Only difference is the align_odd
221 ***********************************************************/
223 static uint8_t *internal_bytes_push_str(uint8_t *buf
, bool ucs2
,
224 const char *str
, size_t str_len
,
226 size_t *pconverted_size
)
228 TALLOC_CTX
*frame
= talloc_stackframe();
231 size_t converted_size
;
234 * This check prevents us from
235 * (re)alloc buf on a NULL TALLOC_CTX.
242 buflen
= talloc_get_size(buf
);
245 ((align_odd
&& (buflen
% 2 == 0)) ||
246 (!align_odd
&& (buflen
% 2 == 1)))) {
248 * We're pushing into an SMB buffer, align odd
250 buf
= talloc_realloc(NULL
, buf
, uint8_t, buflen
+ 1);
259 if (!convert_string_talloc(frame
, CH_UNIX
,
260 ucs2
? CH_UTF16LE
: CH_DOS
,
261 str
, str_len
, &converted
,
267 buf
= talloc_realloc(NULL
, buf
, uint8_t,
268 buflen
+ converted_size
);
274 memcpy(buf
+ buflen
, converted
, converted_size
);
276 TALLOC_FREE(converted
);
278 if (pconverted_size
) {
279 *pconverted_size
= converted_size
;
286 /***********************************************************
287 Push a string into an SMB buffer, with odd byte alignment
288 if it's a UCS2 string.
289 ***********************************************************/
291 uint8_t *smb_bytes_push_str(uint8_t *buf
, bool ucs2
,
292 const char *str
, size_t str_len
,
293 size_t *pconverted_size
)
295 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
296 true, pconverted_size
);
299 uint8_t *smb_bytes_push_bytes(uint8_t *buf
, uint8_t prefix
,
300 const uint8_t *bytes
, size_t num_bytes
)
305 * This check prevents us from
306 * (re)alloc buf on a NULL TALLOC_CTX.
311 buflen
= talloc_get_size(buf
);
313 buf
= talloc_realloc(NULL
, buf
, uint8_t,
314 buflen
+ 1 + num_bytes
);
318 buf
[buflen
] = prefix
;
319 memcpy(&buf
[buflen
+1], bytes
, num_bytes
);
323 /***********************************************************
324 Same as smb_bytes_push_str(), but without the odd byte
325 align for ucs2 (we're pushing into a param or data block).
326 static for now, although this will probably change when
327 other modules use async trans calls.
328 ***********************************************************/
330 uint8_t *trans2_bytes_push_str(uint8_t *buf
, bool ucs2
,
331 const char *str
, size_t str_len
,
332 size_t *pconverted_size
)
334 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
335 false, pconverted_size
);
338 uint8_t *trans2_bytes_push_bytes(uint8_t *buf
,
339 const uint8_t *bytes
, size_t num_bytes
)
346 buflen
= talloc_get_size(buf
);
348 buf
= talloc_realloc(NULL
, buf
, uint8_t,
353 memcpy(&buf
[buflen
], bytes
, num_bytes
);
357 static NTSTATUS
internal_bytes_pull_str(TALLOC_CTX
*mem_ctx
, char **_str
,
358 bool ucs2
, bool align_odd
,
359 const uint8_t *buf
, size_t buf_len
,
360 const uint8_t *position
,
370 if (p_consumed
!= NULL
) {
374 if (position
< buf
) {
375 return NT_STATUS_INTERNAL_ERROR
;
378 offset
= PTR_DIFF(position
, buf
);
379 if (offset
> buf_len
) {
380 return NT_STATUS_BUFFER_TOO_SMALL
;
384 ((align_odd
&& (offset
% 2 == 0)) ||
385 (!align_odd
&& (offset
% 2 == 1)))) {
390 if (offset
> buf_len
) {
391 return NT_STATUS_BUFFER_TOO_SMALL
;
398 buf_len
= utf16_len_n(buf
, buf_len
);
400 size_t tmp
= strnlen((const char *)buf
, buf_len
);
407 ok
= convert_string_talloc(mem_ctx
,
408 ucs2
? CH_UTF16LE
: CH_DOS
,
413 return map_nt_error_from_unix_common(errno
);
416 if (p_consumed
!= NULL
) {
417 *p_consumed
= buf_len
+ pad
;
423 NTSTATUS
smb_bytes_pull_str(TALLOC_CTX
*mem_ctx
, char **_str
, bool ucs2
,
424 const uint8_t *buf
, size_t buf_len
,
425 const uint8_t *position
,
428 return internal_bytes_pull_str(mem_ctx
, _str
, ucs2
, true,
429 buf
, buf_len
, position
, _consumed
);