]> git.samba.org - amitay/samba.git/blob - source3/registry/reg_parse_internal.c
s3-prefork: Improve error detection when handling new connections
[amitay/samba.git] / source3 / registry / reg_parse_internal.c
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 size_t iconvert_talloc(const void* ctx,
34                        smb_iconv_t cd,
35                        const char* src, size_t srclen,
36                        char** pdst)
37 {
38         size_t dstlen, ret;
39         size_t obytes, ibytes;
40         char *optr, *dst, *tmp;
41         const char* iptr;
42
43         if (cd == NULL || cd == ((smb_iconv_t)-1)) {
44                 return -1;
45         }
46
47         dst = *pdst;
48
49         if (dst == NULL) {
50                 /*
51                  * Allocate an extra two bytes for the
52                  * terminating zero.
53                  */
54                 dstlen = srclen + 2;
55                 dst = (char *)talloc_size(ctx, dstlen);
56                 if (dst == NULL) {
57                         DEBUG(0,("iconver_talloc no mem\n"));
58                         return -1;
59                 }
60         } else {
61                 dstlen = talloc_get_size(dst);
62         }
63 convert:
64         iptr   = src;
65         ibytes = srclen;
66         optr   = dst;
67         obytes = dstlen-2;
68
69         ret = smb_iconv(cd, &iptr, &ibytes, &optr, &obytes);
70
71         if(ret == -1) {
72                 const char *reason="unknown error";
73                 switch(errno) {
74                 case EINVAL:
75                         reason="Incomplete multibyte sequence";
76                         break;
77                 case E2BIG:
78                         dstlen = 2*dstlen + 2;
79                         tmp    = talloc_realloc(ctx, dst, char, dstlen);
80                         if (tmp == NULL) {
81                                 reason="talloc_realloc failed";
82                                 break;
83                         }
84                         dst = tmp;
85                         goto convert;
86                 case EILSEQ:
87                         reason="Illegal multibyte sequence";
88                         break;
89                 }
90                 DEBUG(0,("Conversion error: %s(%.80s) %li\n", reason, iptr,
91                          (long int)(iptr-src)));
92                 talloc_free(dst);
93                 return -1;
94         }
95
96         dstlen = (dstlen-2) - obytes;
97
98         SSVAL(dst, dstlen, 0);
99
100         *pdst = dst;
101         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 static 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 static 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 const struct hive_info* hive_info(const char* name, int nlen)
144 {
145         const struct hive_info** info;
146         char buf[32];
147         int s;
148
149         if (nlen >= sizeof(buf)) {
150                 return NULL;
151         }
152         for (s=0; s<nlen; s++) {
153                 buf[s] = toupper(name[s]);
154         }
155         buf[s] = '\0';
156
157         if ((s < 3) || (strncmp(buf, "HK", 2) != 0)) {
158                 return NULL;
159         }
160
161         if (s <= 4) {
162                 for(info = HIVE_INFO; *info; info++) {
163                         if (strcmp(buf+2, (*info)->short_name+2) == 0) {
164                                 return *info;
165                         }
166                 }
167                 return NULL;
168         }
169
170         if ((s < 10) || (strncmp(buf, "HKEY_", 5)) != 0) {
171                 return NULL;
172         }
173
174         for(info = HIVE_INFO; *info; info++) {
175                 if (strcmp(buf+5, (*info)->long_name+5) == 0) {
176                         return *info;
177                 }
178         }
179         return NULL;
180 }
181
182 const char* get_charset(const char* c)
183 {
184         if (strcmp(c, "dos") == 0) {
185                 return lp_dos_charset();
186         } else if (strcmp(c, "unix") == 0) {
187                 return lp_unix_charset();
188         } else {
189                 return c;
190         }
191 }
192
193 bool set_iconv(smb_iconv_t* t, const char* to, const char* from)
194 {
195         smb_iconv_t cd = (smb_iconv_t)-1;
196
197         if (to && from) {
198                 to   = get_charset(to);
199                 from = get_charset(from);
200                 cd   = smb_iconv_open(to, from);
201                 if (cd == ((smb_iconv_t)-1)) {
202                         return false;
203                 }
204         }
205         if ((*t != (smb_iconv_t)NULL) && (*t != (smb_iconv_t)-1)) {
206                 smb_iconv_close(*t);
207         }
208         *t = cd;
209         return true;
210 }
211
212 /**
213  * Parse option string
214  * @param[in,out] ptr parse position
215  * @param[in] mem_ctx talloc context
216  * @param[out] name ptr 2 value
217  * @param[out] value ptr 2 value
218  * @return true on success
219  */
220 bool srprs_option(const char** ptr, const void* mem_ctx, char** name, char** value)
221 {
222         const char* pos = *ptr;
223         void* ctx = talloc_new(mem_ctx);
224
225         cbuf* key = cbuf_new(ctx);
226         cbuf* val = NULL;
227
228         while(srprs_charsetinv(&pos, ",= \t\n\r", key))
229                 ;
230         if (pos == *ptr) {
231                 talloc_free(ctx);
232                 return false;
233         }
234
235         if (name != NULL) {
236                 *name = talloc_steal(mem_ctx, cbuf_gets(key, 0));
237         }
238
239         if (*pos == '=') {
240                 val = cbuf_new(ctx);
241                 pos++;
242                 if (!srprs_quoted_string(ptr, val, NULL)) {
243                         while(srprs_charsetinv(&pos, ", \t\n\r", val))
244                                 ;
245                 }
246                 if (value != NULL) {
247                         *value = talloc_steal(mem_ctx, cbuf_gets(val, 0));
248                 }
249         } else {
250                 if (value != NULL) {
251                         *value = NULL;
252                 }
253         }
254
255         while(srprs_char(&pos, ','))
256                 ;
257
258         *ptr = pos;
259         return true;
260 }
261
262 #define CH_INVALID ((charset_t)-1)
263 static const struct {
264         const char* const name;
265         charset_t ctype;
266         int  len;
267         char seq[4];
268 } BOM[] = {
269         {"UTF-8",    CH_UTF8,    3, {0xEF, 0xBB, 0xBF}},
270         {"UTF-32LE", CH_INVALID, 4, {0xFF, 0xFE, 0x00, 0x00}},
271         {"UTF-16LE", CH_UTF16LE, 2, {0xFF, 0xFE}},
272         {"UTF-16BE", CH_UTF16BE, 2, {0xFE, 0xFF}},
273         {"UTF-32BE", CH_INVALID, 4, {0x00, 0x00, 0xFE, 0xFF}},
274         {NULL,       CH_INVALID, 0}
275 };
276
277 bool srprs_bom(const char** ptr, const char** name, charset_t* ctype)
278 {
279         int i;
280         for (i=0; BOM[i].name; i++) {
281                 if (memcmp(*ptr, BOM[i].seq, BOM[i].len) == 0) {
282                         break;
283                 }
284         }
285
286         if (BOM[i].name != NULL) {
287                 DEBUG(0, ("Found Byte Order Mark for : %s\n", BOM[i].name));
288
289                 if (name != NULL) {
290                         *name  = BOM[i].name;
291                 }
292
293                 if (ctype != NULL) {
294                         *ctype = BOM[i].ctype;
295                 }
296
297                 *ptr  += BOM[i].len;
298
299                 return true;
300         }
301         return false;
302 }
303
304 int write_bom(FILE* file, const char* charset, charset_t ctype)
305 {
306         int i;
307         if ( charset == NULL ) {
308                 for (i=0; BOM[i].name; i++) {
309                         if (BOM[i].ctype == ctype) {
310                                 return fwrite(BOM[i].seq, 1, BOM[i].len, file);
311                         }
312                 }
313                 DEBUG(0, ("No Byte Order Mark for charset_t: %u\n", (unsigned)ctype));
314         } else {
315                 for (i=0; BOM[i].name; i++) {
316                         if (strcasecmp_m(BOM[i].name, charset) == 0) {
317                                 return fwrite(BOM[i].seq, 1, BOM[i].len, file);
318                         }
319                 }
320                 DEBUG(0, ("No Byte Order Mark for charset_t: %s\n", charset));
321         }
322         return 0;
323 }
324
325
326 int cbuf_puts_case(cbuf* s, const char* str, size_t len, enum fmt_case fmt)
327 {
328         size_t pos = cbuf_getpos(s);
329         int ret = cbuf_puts(s, str, len);
330         char* ptr = cbuf_gets(s,pos);
331
332         if (ret <= 0) {
333                 return ret;
334         }
335
336         switch (fmt) {
337         case FMT_CASE_PRESERVE:
338                 break;
339         case FMT_CASE_UPPER:
340                 while(*ptr != '\0') {
341                         *ptr = toupper(*ptr);
342                         ptr++;
343                 }
344                 break;
345         case FMT_CASE_TITLE:
346                 *ptr = toupper(*ptr);
347                 ptr++;
348         case FMT_CASE_LOWER:
349                 while(*ptr != '\0') {
350                         *ptr = tolower(*ptr);
351                         ptr++;
352                 }
353         }
354         return ret;
355 }