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"
27 Return a string representing a CIFS attribute for a file.
29 char *attrib_string(TALLOC_CTX
*mem_ctx
, uint32_t attrib
)
36 {'V', FILE_ATTRIBUTE_VOLUME
},
37 {'D', FILE_ATTRIBUTE_DIRECTORY
},
38 {'A', FILE_ATTRIBUTE_ARCHIVE
},
39 {'H', FILE_ATTRIBUTE_HIDDEN
},
40 {'S', FILE_ATTRIBUTE_SYSTEM
},
41 {'N', FILE_ATTRIBUTE_NORMAL
},
42 {'R', FILE_ATTRIBUTE_READONLY
},
43 {'d', FILE_ATTRIBUTE_DEVICE
},
44 {'t', FILE_ATTRIBUTE_TEMPORARY
},
45 {'s', FILE_ATTRIBUTE_SPARSE
},
46 {'r', FILE_ATTRIBUTE_REPARSE_POINT
},
47 {'c', FILE_ATTRIBUTE_COMPRESSED
},
48 {'o', FILE_ATTRIBUTE_OFFLINE
},
49 {'n', FILE_ATTRIBUTE_NONINDEXED
},
50 {'e', FILE_ATTRIBUTE_ENCRYPTED
}
54 ret
= talloc_array(mem_ctx
, char, ARRAY_SIZE(attr_strs
)+1);
59 for (len
=i
=0; i
<ARRAY_SIZE(attr_strs
); i
++) {
60 if (attrib
& attr_strs
[i
].attr
) {
61 ret
[len
++] = attr_strs
[i
].c
;
67 talloc_set_name_const(ret
, ret
);
72 /****************************************************************************
73 Map standard UNIX permissions onto wire representations.
74 ****************************************************************************/
76 uint32_t unix_perms_to_wire(mode_t perms
)
80 ret
|= ((perms
& S_IXOTH
) ? UNIX_X_OTH
: 0);
81 ret
|= ((perms
& S_IWOTH
) ? UNIX_W_OTH
: 0);
82 ret
|= ((perms
& S_IROTH
) ? UNIX_R_OTH
: 0);
83 ret
|= ((perms
& S_IXGRP
) ? UNIX_X_GRP
: 0);
84 ret
|= ((perms
& S_IWGRP
) ? UNIX_W_GRP
: 0);
85 ret
|= ((perms
& S_IRGRP
) ? UNIX_R_GRP
: 0);
86 ret
|= ((perms
& S_IXUSR
) ? UNIX_X_USR
: 0);
87 ret
|= ((perms
& S_IWUSR
) ? UNIX_W_USR
: 0);
88 ret
|= ((perms
& S_IRUSR
) ? UNIX_R_USR
: 0);
90 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
93 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
96 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
101 /****************************************************************************
102 Map wire permissions to standard UNIX.
103 ****************************************************************************/
105 mode_t
wire_perms_to_unix(uint32_t perms
)
107 mode_t ret
= (mode_t
)0;
109 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
110 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
111 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
112 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
113 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
114 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
115 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
116 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
117 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
119 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
122 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
125 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
130 /****************************************************************************
131 Return the file type from the wire filetype for UNIX extensions.
132 ****************************************************************************/
134 mode_t
unix_filetype_from_wire(uint32_t wire_type
)
142 case UNIX_TYPE_SYMLINK
:
146 case UNIX_TYPE_CHARDEV
:
150 case UNIX_TYPE_BLKDEV
:
158 case UNIX_TYPE_SOCKET
:
166 bool smb_buffer_oob(uint32_t bufsize
, uint32_t offset
, uint32_t length
)
168 if ((offset
+ length
< offset
) || (offset
+ length
< length
)) {
172 if ((offset
> bufsize
) || (offset
+ length
> bufsize
)) {
179 /***********************************************************
180 Common function for pushing stings, used by smb_bytes_push_str()
181 and trans_bytes_push_str(). Only difference is the align_odd
183 ***********************************************************/
185 static uint8_t *internal_bytes_push_str(uint8_t *buf
, bool ucs2
,
186 const char *str
, size_t str_len
,
188 size_t *pconverted_size
)
190 TALLOC_CTX
*frame
= talloc_stackframe();
193 size_t converted_size
;
196 * This check prevents us from
197 * (re)alloc buf on a NULL TALLOC_CTX.
204 buflen
= talloc_get_size(buf
);
207 ((align_odd
&& (buflen
% 2 == 0)) ||
208 (!align_odd
&& (buflen
% 2 == 1)))) {
210 * We're pushing into an SMB buffer, align odd
212 buf
= talloc_realloc(NULL
, buf
, uint8_t, buflen
+ 1);
221 if (!convert_string_talloc(frame
, CH_UNIX
,
222 ucs2
? CH_UTF16LE
: CH_DOS
,
223 str
, str_len
, &converted
,
229 buf
= talloc_realloc(NULL
, buf
, uint8_t,
230 buflen
+ converted_size
);
236 memcpy(buf
+ buflen
, converted
, converted_size
);
238 TALLOC_FREE(converted
);
240 if (pconverted_size
) {
241 *pconverted_size
= converted_size
;
248 /***********************************************************
249 Push a string into an SMB buffer, with odd byte alignment
250 if it's a UCS2 string.
251 ***********************************************************/
253 uint8_t *smb_bytes_push_str(uint8_t *buf
, bool ucs2
,
254 const char *str
, size_t str_len
,
255 size_t *pconverted_size
)
257 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
258 true, pconverted_size
);
261 uint8_t *smb_bytes_push_bytes(uint8_t *buf
, uint8_t prefix
,
262 const uint8_t *bytes
, size_t num_bytes
)
267 * This check prevents us from
268 * (re)alloc buf on a NULL TALLOC_CTX.
273 buflen
= talloc_get_size(buf
);
275 buf
= talloc_realloc(NULL
, buf
, uint8_t,
276 buflen
+ 1 + num_bytes
);
280 buf
[buflen
] = prefix
;
281 memcpy(&buf
[buflen
+1], bytes
, num_bytes
);
285 /***********************************************************
286 Same as smb_bytes_push_str(), but without the odd byte
287 align for ucs2 (we're pushing into a param or data block).
288 static for now, although this will probably change when
289 other modules use async trans calls.
290 ***********************************************************/
292 uint8_t *trans2_bytes_push_str(uint8_t *buf
, bool ucs2
,
293 const char *str
, size_t str_len
,
294 size_t *pconverted_size
)
296 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
297 false, pconverted_size
);
300 uint8_t *trans2_bytes_push_bytes(uint8_t *buf
,
301 const uint8_t *bytes
, size_t num_bytes
)
308 buflen
= talloc_get_size(buf
);
310 buf
= talloc_realloc(NULL
, buf
, uint8_t,
315 memcpy(&buf
[buflen
], bytes
, num_bytes
);
319 static NTSTATUS
internal_bytes_pull_str(TALLOC_CTX
*mem_ctx
, char **_str
,
320 bool ucs2
, bool align_odd
,
321 const uint8_t *buf
, size_t buf_len
,
322 size_t *pbuf_consumed
)
330 if (pbuf_consumed
!= NULL
) {
335 ((align_odd
&& (buf_len
% 2 == 0)) ||
336 (!align_odd
&& (buf_len
% 2 == 1)))) {
338 return NT_STATUS_BUFFER_TOO_SMALL
;
346 buf_len
= utf16_len_n(buf
, buf_len
);
348 size_t tmp
= strnlen((const char *)buf
, buf_len
);
355 ok
= convert_string_talloc(mem_ctx
,
356 ucs2
? CH_UTF16LE
: CH_DOS
,
361 return map_nt_error_from_unix_common(errno
);
364 if (pbuf_consumed
!= NULL
) {
365 *pbuf_consumed
= buf_len
+ pad
;
368 return NT_STATUS_OK
;;
371 NTSTATUS
smb_bytes_pull_str(TALLOC_CTX
*mem_ctx
, char **_str
, bool ucs2
,
372 const uint8_t *buf
, size_t buf_len
,
373 size_t *_buf_consumed
)
375 return internal_bytes_pull_str(mem_ctx
, _str
, ucs2
, true,
376 buf
, buf_len
, _buf_consumed
);