Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * Registry helper routines
5 : *
6 : * Copyright (C) Gregor Beck 2010
7 : *
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.
12 : *
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.
17 : *
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/>.
20 : */
21 : /**
22 : * @file reg_parse_internal.h
23 : * @author Gregor Beck <gb@sernet.de>
24 : * @date Sep 2010
25 : * @brief
26 : */
27 :
28 : #include "reg_parse_internal.h"
29 : #include "cbuf.h"
30 : #include "srprs.h"
31 : #include "registry.h"
32 :
33 3838 : size_t iconvert_talloc(const void* ctx,
34 : smb_iconv_t cd,
35 : const char* src, size_t srclen,
36 : char** pdst)
37 : {
38 0 : size_t dstlen, ret;
39 0 : size_t obytes, ibytes;
40 0 : char *optr, *dst, *tmp;
41 0 : const char* iptr;
42 :
43 3838 : if (cd == NULL || cd == ((smb_iconv_t)-1)) {
44 0 : return -1;
45 : }
46 :
47 3838 : dst = *pdst;
48 :
49 3838 : if (dst == NULL) {
50 : /*
51 : * Allocate an extra two bytes for the
52 : * terminating zero.
53 : */
54 3838 : dstlen = srclen + 2;
55 3838 : dst = (char *)talloc_size(ctx, dstlen);
56 3838 : if (dst == NULL) {
57 0 : DEBUG(0,("iconver_talloc no mem\n"));
58 0 : return -1;
59 : }
60 : } else {
61 0 : dstlen = talloc_get_size(dst);
62 : }
63 3838 : convert:
64 3838 : iptr = src;
65 3838 : ibytes = srclen;
66 3838 : optr = dst;
67 3838 : obytes = dstlen-2;
68 :
69 3838 : ret = smb_iconv(cd, &iptr, &ibytes, &optr, &obytes);
70 :
71 3838 : if(ret == -1) {
72 0 : const char *reason="unknown error";
73 0 : switch(errno) {
74 0 : case EINVAL:
75 0 : reason="Incomplete multibyte sequence";
76 0 : break;
77 0 : case E2BIG:
78 0 : dstlen = 2*dstlen + 2;
79 0 : tmp = talloc_realloc(ctx, dst, char, dstlen);
80 0 : if (tmp == NULL) {
81 0 : reason="talloc_realloc failed";
82 0 : break;
83 : }
84 0 : dst = tmp;
85 0 : goto convert;
86 0 : case EILSEQ:
87 0 : reason="Illegal multibyte sequence";
88 0 : break;
89 : }
90 0 : DEBUG(0,("Conversion error: %s(%.80s) %li\n", reason, iptr,
91 : (long int)(iptr-src)));
92 0 : talloc_free(dst);
93 0 : return -1;
94 : }
95 :
96 3838 : dstlen = (dstlen-2) - obytes;
97 :
98 3838 : SSVAL(dst, dstlen, 0);
99 :
100 3838 : *pdst = dst;
101 3838 : return dstlen;
102 : }
103 :
104 : #ifndef HKEY_CURRENT_CONFIG
105 : #define HKEY_CURRENT_CONFIG 0x80000005
106 : #endif
107 : #ifndef HKEY_DYN_DATA
108 : #define HKEY_DYN_DATA 0x80000006
109 : #endif
110 : #ifndef HKEY_PERFORMANCE_TEXT
111 : #define HKEY_PERFORMANCE_TEXT 0x80000050
112 : #endif
113 : #ifndef HKEY_PERFORMANCE_NLSTEXT
114 : #define HKEY_PERFORMANCE_NLSTEXT 0x80000060
115 : #endif
116 :
117 : #define HIVE_INFO_ENTRY(SHORT,LONG) \
118 : const struct hive_info HIVE_INFO_##SHORT = { \
119 : .handle = LONG, \
120 : .short_name = #SHORT, \
121 : .short_name_len = sizeof(#SHORT)-1, \
122 : .long_name = #LONG, \
123 : .long_name_len = sizeof(#LONG)-1, \
124 : }
125 :
126 : HIVE_INFO_ENTRY(HKLM, HKEY_LOCAL_MACHINE);
127 : HIVE_INFO_ENTRY(HKCU, HKEY_CURRENT_USER);
128 : HIVE_INFO_ENTRY(HKCR, HKEY_CLASSES_ROOT);
129 : HIVE_INFO_ENTRY(HKU , HKEY_USERS);
130 : HIVE_INFO_ENTRY(HKCC, HKEY_CURRENT_CONFIG);
131 : HIVE_INFO_ENTRY(HKDD, HKEY_DYN_DATA);
132 : HIVE_INFO_ENTRY(HKPD, HKEY_PERFORMANCE_DATA);
133 : HIVE_INFO_ENTRY(HKPT, HKEY_PERFORMANCE_TEXT);
134 : HIVE_INFO_ENTRY(HKPN, HKEY_PERFORMANCE_NLSTEXT);
135 : #undef HIVE_INFO_ENTRY
136 :
137 : const struct hive_info* HIVE_INFO[] = {
138 : &HIVE_INFO_HKLM, &HIVE_INFO_HKCU, &HIVE_INFO_HKCR, &HIVE_INFO_HKU,
139 : &HIVE_INFO_HKCC, &HIVE_INFO_HKDD, &HIVE_INFO_HKPD, &HIVE_INFO_HKPT,
140 : &HIVE_INFO_HKPN, NULL
141 : };
142 :
143 : #define TOINT(A,B) ((int)(A) << 8) + (int)(B)
144 :
145 48880 : bool srprs_hive(const char** ptr, const struct hive_info** result)
146 : {
147 48880 : const char* str = *ptr;
148 48880 : const struct hive_info* info = NULL;
149 48880 : bool long_hive = false;
150 :
151 48880 : if ((toupper(str[0]) != 'H') || (toupper(str[1]) != 'K')
152 48514 : || (str[2] == '\0') )
153 : {
154 366 : return false;
155 : }
156 :
157 48514 : switch ( TOINT(toupper(str[2]), toupper(str[3])) ) {
158 0 : case TOINT('E', 'Y'):
159 0 : if (str[4] == '_') {
160 : int i;
161 0 : for (i=0; (info = HIVE_INFO[i]); i++) {
162 0 : if (strncmp(&str[5], &info->long_name[5],
163 0 : info->long_name_len-5) == 0)
164 : {
165 0 : long_hive = true;
166 0 : break;
167 : }
168 : }
169 : }
170 0 : break;
171 48124 : case TOINT('L', 'M'):
172 48124 : info = &HIVE_INFO_HKLM;
173 48124 : break;
174 217 : case TOINT('C', 'U'):
175 217 : info = &HIVE_INFO_HKCU;
176 217 : break;
177 41 : case TOINT('C', 'R'):
178 41 : info = &HIVE_INFO_HKCR;
179 41 : break;
180 0 : case TOINT('C', 'C'):
181 0 : info = &HIVE_INFO_HKCC;
182 0 : break;
183 0 : case TOINT('D', 'D'):
184 0 : info = &HIVE_INFO_HKDD;
185 0 : break;
186 34 : case TOINT('P', 'D'):
187 34 : info = &HIVE_INFO_HKPD;
188 34 : break;
189 34 : case TOINT('P', 'T'):
190 34 : info = &HIVE_INFO_HKPT;
191 34 : break;
192 0 : case TOINT('P', 'N'):
193 0 : info = &HIVE_INFO_HKPN;
194 0 : break;
195 41 : default:
196 41 : if (toupper(str[2]) == 'U') {
197 41 : info = &HIVE_INFO_HKU;
198 : }
199 41 : break;
200 : }
201 48514 : if (info != NULL) {
202 48514 : if (result != NULL) {
203 46252 : *result = info;
204 : }
205 48514 : *ptr += long_hive ? info->long_name_len : info->short_name_len;
206 48514 : return true;
207 : }
208 0 : return false;
209 : }
210 :
211 46254 : const struct hive_info* hive_info(const char* name)
212 : {
213 46254 : const struct hive_info* info = NULL;
214 46254 : srprs_hive(&name, &info);
215 46254 : return info;
216 : }
217 :
218 138 : const char *smbreg_get_charset(const char *c)
219 : {
220 138 : if (strcmp(c, "dos") == 0) {
221 0 : return lp_dos_charset();
222 138 : } else if (strcmp(c, "unix") == 0) {
223 62 : return lp_unix_charset();
224 : } else {
225 76 : return c;
226 : }
227 : }
228 :
229 82 : bool set_iconv(smb_iconv_t* t, const char* to, const char* from)
230 : {
231 82 : smb_iconv_t cd = (smb_iconv_t)-1;
232 :
233 82 : if (to && from) {
234 62 : to = smbreg_get_charset(to);
235 62 : from = smbreg_get_charset(from);
236 62 : cd = smb_iconv_open(to, from);
237 62 : if (cd == ((smb_iconv_t)-1)) {
238 0 : return false;
239 : }
240 : }
241 82 : if ((*t != (smb_iconv_t)NULL) && (*t != (smb_iconv_t)-1)) {
242 34 : smb_iconv_close(*t);
243 : }
244 82 : *t = cd;
245 82 : return true;
246 : }
247 :
248 : /**
249 : * Parse option string
250 : * @param[in,out] ptr parse position
251 : * @param[in] mem_ctx talloc context
252 : * @param[out] name ptr 2 value
253 : * @param[out] value ptr 2 value
254 : * @return true on success
255 : */
256 0 : bool srprs_option(const char** ptr, const void* mem_ctx, char** name, char** value)
257 : {
258 0 : const char* pos = *ptr;
259 0 : void* ctx = talloc_new(mem_ctx);
260 :
261 0 : cbuf* key = cbuf_new(ctx);
262 0 : cbuf* val = NULL;
263 :
264 0 : while(srprs_charsetinv(&pos, ",= \t\n\r", key))
265 : ;
266 0 : if (pos == *ptr) {
267 0 : talloc_free(ctx);
268 0 : return false;
269 : }
270 :
271 0 : if (name != NULL) {
272 0 : *name = talloc_steal(mem_ctx, cbuf_gets(key, 0));
273 : }
274 :
275 0 : if (*pos == '=') {
276 0 : val = cbuf_new(ctx);
277 0 : pos++;
278 0 : if (!srprs_quoted_string(ptr, val, NULL)) {
279 0 : while(srprs_charsetinv(&pos, ", \t\n\r", val))
280 : ;
281 : }
282 0 : if (value != NULL) {
283 0 : *value = talloc_steal(mem_ctx, cbuf_gets(val, 0));
284 : }
285 : } else {
286 0 : if (value != NULL) {
287 0 : *value = NULL;
288 : }
289 : }
290 :
291 0 : while(srprs_char(&pos, ','))
292 : ;
293 :
294 0 : *ptr = pos;
295 0 : return true;
296 : }
297 :
298 : #define CH_INVALID ((charset_t)-1)
299 : static const struct {
300 : const char* const name;
301 : charset_t ctype;
302 : int len;
303 : uint8_t seq[4];
304 : } BOM[] = {
305 : {"UTF-8", CH_UTF8, 3, {0xEF, 0xBB, 0xBF}},
306 : {"UTF-32LE", CH_INVALID, 4, {0xFF, 0xFE, 0x00, 0x00}},
307 : {"UTF-16LE", CH_UTF16LE, 2, {0xFF, 0xFE}},
308 : {"UTF-16BE", CH_UTF16BE, 2, {0xFE, 0xFF}},
309 : {"UTF-32BE", CH_INVALID, 4, {0x00, 0x00, 0xFE, 0xFF}},
310 : { .name = NULL }
311 : };
312 :
313 10 : bool srprs_bom(const char** ptr, const char** name, charset_t* ctype)
314 : {
315 0 : int i;
316 54 : for (i=0; BOM[i].name; i++) {
317 46 : if (memcmp(*ptr, BOM[i].seq, BOM[i].len) == 0) {
318 2 : break;
319 : }
320 : }
321 :
322 10 : if (BOM[i].name != NULL) {
323 2 : DEBUG(0, ("Found Byte Order Mark for : %s\n", BOM[i].name));
324 :
325 2 : if (name != NULL) {
326 2 : *name = BOM[i].name;
327 : }
328 :
329 2 : if (ctype != NULL) {
330 0 : *ctype = BOM[i].ctype;
331 : }
332 :
333 2 : *ptr += BOM[i].len;
334 :
335 2 : return true;
336 : }
337 8 : return false;
338 : }
339 :
340 0 : int write_bom(FILE* file, const char* charset, charset_t ctype)
341 : {
342 0 : int i;
343 0 : if ( charset == NULL ) {
344 0 : for (i=0; BOM[i].name; i++) {
345 0 : if (BOM[i].ctype == ctype) {
346 0 : return fwrite(BOM[i].seq, 1, BOM[i].len, file);
347 : }
348 : }
349 0 : DEBUG(0, ("No Byte Order Mark for charset_t: %u\n", (unsigned)ctype));
350 : } else {
351 0 : for (i=0; BOM[i].name; i++) {
352 0 : if (strcasecmp_m(BOM[i].name, charset) == 0) {
353 0 : return fwrite(BOM[i].seq, 1, BOM[i].len, file);
354 : }
355 : }
356 0 : DEBUG(0, ("No Byte Order Mark for charset_t: %s\n", charset));
357 : }
358 0 : return 0;
359 : }
360 :
361 :
362 3764 : int cbuf_puts_case(cbuf* s, const char* str, size_t len, enum fmt_case fmt)
363 : {
364 3764 : size_t pos = cbuf_getpos(s);
365 3764 : int ret = cbuf_puts(s, str, len);
366 3764 : char* ptr = cbuf_gets(s,pos);
367 :
368 3764 : if (ret <= 0) {
369 0 : return ret;
370 : }
371 :
372 3764 : switch (fmt) {
373 3764 : case FMT_CASE_PRESERVE:
374 3764 : break;
375 0 : case FMT_CASE_UPPER:
376 0 : while(*ptr != '\0') {
377 0 : *ptr = toupper(*ptr);
378 0 : ptr++;
379 : }
380 0 : break;
381 0 : case FMT_CASE_TITLE:
382 0 : *ptr = toupper(*ptr);
383 0 : ptr++;
384 : FALL_THROUGH;
385 0 : case FMT_CASE_LOWER:
386 0 : while(*ptr != '\0') {
387 0 : *ptr = tolower(*ptr);
388 0 : ptr++;
389 : }
390 : }
391 3764 : return ret;
392 : }
|