Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * Copyright (C) Volker Lendecke, 2005
5 : * Copyright (C) Aravind Srinivasan, 2009
6 : * Copyright (C) Guenter Kukkukk, 2013
7 : * Copyright (C) Ralph Boehme, 2017
8 : *
9 : * This program is free software; you can redistribute it and/or modify
10 : * it under the terms of the GNU General Public License as published by
11 : * the Free Software Foundation; either version 3 of the License, or
12 : * (at your option) any later version.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "smbd/smbd.h"
25 : #include "string_replace.h"
26 : #include "lib/util/string_wrappers.h"
27 :
28 : #define MAP_SIZE 0xFF
29 : #define MAP_NUM 0x101 /* max unicode charval / MAP_SIZE */
30 : #define T_OFFSET(_v_) ((_v_ % MAP_SIZE))
31 : #define T_START(_v_) (((_v_ / MAP_SIZE) * MAP_SIZE))
32 : #define T_PICK(_v_) ((_v_ / MAP_SIZE))
33 :
34 : struct char_mappings {
35 : smb_ucs2_t entry[MAP_SIZE][2];
36 : };
37 :
38 394 : static bool build_table(struct char_mappings **cmaps, int value)
39 : {
40 0 : int i;
41 394 : int start = T_START(value);
42 :
43 394 : (*cmaps) = talloc_zero(NULL, struct char_mappings);
44 :
45 394 : if (!*cmaps)
46 0 : return False;
47 :
48 100864 : for (i = 0; i < MAP_SIZE;i++) {
49 100470 : (*cmaps)->entry[i][vfs_translate_to_unix] = start + i;
50 100470 : (*cmaps)->entry[i][vfs_translate_to_windows] = start + i;
51 : }
52 :
53 394 : return True;
54 : }
55 :
56 4994 : static void set_tables(struct char_mappings **cmaps,
57 : long unix_map,
58 : long windows_map)
59 : {
60 0 : int i;
61 :
62 : /* set unix -> windows */
63 4994 : i = T_OFFSET(unix_map);
64 4994 : cmaps[T_PICK(unix_map)]->entry[i][vfs_translate_to_windows] = windows_map;
65 :
66 : /* set windows -> unix */
67 4994 : i = T_OFFSET(windows_map);
68 4994 : cmaps[T_PICK(windows_map)]->entry[i][vfs_translate_to_unix] = unix_map;
69 4994 : }
70 :
71 4994 : static bool build_ranges(struct char_mappings **cmaps,
72 : long unix_map,
73 : long windows_map)
74 : {
75 :
76 4994 : if (!cmaps[T_PICK(unix_map)]) {
77 134 : if (!build_table(&cmaps[T_PICK(unix_map)], unix_map))
78 0 : return False;
79 : }
80 :
81 4994 : if (!cmaps[T_PICK(windows_map)]) {
82 260 : if (!build_table(&cmaps[T_PICK(windows_map)], windows_map))
83 0 : return False;
84 : }
85 :
86 4994 : set_tables(cmaps, unix_map, windows_map);
87 :
88 4994 : return True;
89 : }
90 :
91 134 : struct char_mappings **string_replace_init_map(TALLOC_CTX *mem_ctx,
92 : const char **mappings)
93 : {
94 0 : int i;
95 0 : char *tmp;
96 0 : fstring mapping;
97 0 : long unix_map, windows_map;
98 134 : struct char_mappings **cmaps = NULL;
99 :
100 134 : if (mappings == NULL) {
101 0 : return NULL;
102 : }
103 :
104 134 : cmaps = talloc_zero_array(mem_ctx, struct char_mappings *, MAP_NUM);
105 134 : if (cmaps == NULL) {
106 0 : return NULL;
107 : }
108 :
109 : /*
110 : * catia mappings are of the form :
111 : * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
112 : *
113 : * multiple mappings are comma separated in smb.conf
114 : */
115 :
116 5128 : for (i = 0; mappings[i]; i++) {
117 4994 : fstrcpy(mapping, mappings[i]);
118 4994 : unix_map = strtol(mapping, &tmp, 16);
119 4994 : if (unix_map == 0 && errno == EINVAL) {
120 0 : DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
121 0 : continue;
122 : }
123 4994 : windows_map = strtol(++tmp, NULL, 16);
124 4994 : if (windows_map == 0 && errno == EINVAL) {
125 0 : DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
126 0 : continue;
127 : }
128 :
129 4994 : if (!build_ranges(cmaps, unix_map, windows_map)) {
130 0 : DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping));
131 0 : continue;
132 : }
133 : }
134 :
135 134 : return cmaps;
136 : }
137 :
138 342002 : NTSTATUS string_replace_allocate(connection_struct *conn,
139 : const char *name_in,
140 : struct char_mappings **cmaps,
141 : TALLOC_CTX *mem_ctx,
142 : char **mapped_name,
143 : enum vfs_translate_direction direction)
144 : {
145 0 : static smb_ucs2_t *tmpbuf = NULL;
146 342002 : smb_ucs2_t *ptr = NULL;
147 342002 : struct char_mappings *map = NULL;
148 0 : size_t converted_size;
149 0 : bool ok;
150 :
151 342002 : ok = push_ucs2_talloc(talloc_tos(), &tmpbuf, name_in,
152 : &converted_size);
153 342002 : if (!ok) {
154 0 : return map_nt_error_from_unix(errno);
155 : }
156 :
157 5607978 : for (ptr = tmpbuf; *ptr; ptr++) {
158 5265976 : if (*ptr == 0) {
159 0 : break;
160 : }
161 5265976 : if (cmaps == NULL) {
162 0 : continue;
163 : }
164 5265976 : map = cmaps[T_PICK((*ptr))];
165 5265976 : if (map == NULL) {
166 : /* nothing to do */
167 0 : continue;
168 : }
169 :
170 5265976 : *ptr = map->entry[T_OFFSET((*ptr))][direction];
171 : }
172 :
173 342002 : ok = pull_ucs2_talloc(mem_ctx, mapped_name, tmpbuf,
174 : &converted_size);
175 342002 : TALLOC_FREE(tmpbuf);
176 342002 : if (!ok) {
177 0 : return map_nt_error_from_unix(errno);
178 : }
179 342002 : return NT_STATUS_OK;
180 : }
181 :
182 : const char *macos_string_replace_map =
183 : "0x01:0xf001,0x02:0xf002,0x03:0xf003,0x04:0xf004,"
184 : "0x05:0xf005,0x06:0xf006,0x07:0xf007,0x08:0xf008,"
185 : "0x09:0xf009,0x0a:0xf00a,0x0b:0xf00b,0x0c:0xf00c,"
186 : "0x0d:0xf00d,0x0e:0xf00e,0x0f:0xf00f,0x10:0xf010,"
187 : "0x11:0xf011,0x12:0xf012,0x13:0xf013,0x14:0xf014,"
188 : "0x15:0xf015,0x16:0xf016,0x17:0xf017,0x18:0xf018,"
189 : "0x19:0xf019,0x1a:0xf01a,0x1b:0xf01b,0x1c:0xf01c,"
190 : "0x1d:0xf01d,0x1e:0xf01e,0x1f:0xf01f,"
191 : "0x22:0xf020,0x2a:0xf021,0x3a:0xf022,0x3c:0xf023,"
192 : "0x3e:0xf024,0x3f:0xf025,0x5c:0xf026,0x7c:0xf027";
|