1 /**
2  * xrdp: A Remote Desktop Protocol server.
3  *
4  * Copyright (C) Jay Sorg 2004-2014
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * read a config file
19  */
20 
21 #if defined(HAVE_CONFIG_H)
22 #include <config_ac.h>
23 #endif
24 
25 #include "arch.h"
26 #include "os_calls.h"
27 #include "string_calls.h"
28 #include "list.h"
29 #include "file.h"
30 #include "parse.h"
31 
32 #define FILE_MAX_LINE_BYTES 2048
33 
34 static int
35 file_read_ini_line(struct stream *s, char *text, int text_bytes);
36 
37 /*****************************************************************************/
38 /* look up for a section name within str (i.e. pattern [section_name])
39  * if a section name is found, this function return 1 and copy the section
40  * inplace of str. */
41 static int
line_lookup_for_section_name(char * str,int str_bytes)42 line_lookup_for_section_name(char *str, int str_bytes)
43 {
44     int name_index_start;
45     int index;
46     char c;
47 
48     name_index_start = -1;
49     index = 0;
50     while ((c = str[index]) != 0)
51     {
52         if (c == '[')
53         {
54             name_index_start = index + 1;
55         }
56         else if (c == ']' && name_index_start > 0)
57         {
58             if (name_index_start + index >= str_bytes)
59             {
60                 return 0;
61             }
62             for (index = index - name_index_start; index > 0; index--)
63             {
64                 str[0] = str[name_index_start];
65                 str++;
66             }
67             str[0] = 0;
68             return 1;
69         }
70         ++index;
71     }
72     return 0;
73 }
74 
75 
76 /*****************************************************************************/
77 /* returns error
78    returns 0 if everything is ok
79    returns 1 if problem reading file */
80 static int
l_file_read_sections(int fd,int max_file_size,struct list * names)81 l_file_read_sections(int fd, int max_file_size, struct list *names)
82 {
83     struct stream *s;
84     char text[FILE_MAX_LINE_BYTES];
85     int len;
86     int rv;
87 
88     rv = 0;
89     g_file_seek(fd, 0);
90     g_memset(text, 0, FILE_MAX_LINE_BYTES);
91     list_clear(names);
92     make_stream(s);
93     init_stream(s, max_file_size);
94     len = g_file_read(fd, s->data, max_file_size);
95 
96     if (len > 0)
97     {
98         s->end = s->p + len;
99         while (file_read_ini_line(s, text, FILE_MAX_LINE_BYTES) == 0)
100         {
101             if (line_lookup_for_section_name(text, FILE_MAX_LINE_BYTES) != 0)
102             {
103                 list_add_item(names, (tbus)g_strdup(text));
104             }
105         }
106     }
107     else if (len < 0)
108     {
109         rv = 1;
110     }
111 
112     free_stream(s);
113     return rv;
114 }
115 
116 /*****************************************************************************/
117 /* Read a line in the stream 's', removing comments.
118  * returns error
119  * returns 0 if everything is ok
120  * returns 1 if problem reading file */
121 static int
file_read_ini_line(struct stream * s,char * text,int text_bytes)122 file_read_ini_line(struct stream *s, char *text, int text_bytes)
123 {
124     int i;
125     int skip_to_end;
126     int at_end;
127     char c;
128 
129     skip_to_end = 0;
130 
131     if (!s_check_rem(s, 1))
132     {
133         return 1;
134     }
135 
136     i = 0;
137     in_uint8(s, c);
138 
139     while (c != 10 && c != 13)
140     {
141         /* these mean skip the rest of the line */
142         if (c == '#' || c == ';')
143         {
144             skip_to_end = 1;
145         }
146 
147         if (!skip_to_end)
148         {
149             text[i] = c;
150             i++;
151             if (i >= text_bytes)
152             {
153                 return 1;
154             }
155         }
156 
157         if (s_check_rem(s, 1))
158         {
159             in_uint8(s, c);
160         }
161         else
162         {
163             c = 0;
164             break;
165         }
166     }
167 
168     if (c == 10 || c == 13)
169     {
170         at_end = 0;
171 
172         while (c == 10 || c == 13)
173         {
174             if (s_check_rem(s, 1))
175             {
176                 in_uint8(s, c);
177             }
178             else
179             {
180                 at_end = 1;
181                 break;
182             }
183         }
184 
185         if (!at_end)
186         {
187             s->p--;
188         }
189     }
190 
191     text[i] = 0;
192 
193     return 0;
194 }
195 
196 
197 /*****************************************************************************/
198 /* returns error */
199 static int
file_split_name_value(char * text,char * name,char * value)200 file_split_name_value(char *text, char *name, char *value)
201 {
202     int len;
203     int i;
204     int value_index;
205     int name_index;
206     int on_to;
207 
208     value_index = 0;
209     name_index = 0;
210     on_to = 0;
211     name[0] = 0;
212     value[0] = 0;
213     len = g_strlen(text);
214 
215     for (i = 0; i < len; i++)
216     {
217         if (text[i] == '=' && !on_to)
218         {
219             on_to = 1;
220         }
221         else if (on_to)
222         {
223             value[value_index] = text[i];
224             value_index++;
225             value[value_index] = 0;
226         }
227         else
228         {
229             name[name_index] = text[i];
230             name_index++;
231             name[name_index] = 0;
232         }
233     }
234 
235     g_strtrim(name, 3); /* trim both right and left */
236     g_strtrim(value, 3); /* trim both right and left */
237     return 0;
238 }
239 
240 /*****************************************************************************/
241 /* return error */
242 static int
l_file_read_section(int fd,int max_file_size,const char * section,struct list * names,struct list * values)243 l_file_read_section(int fd, int max_file_size, const char *section,
244                     struct list *names, struct list *values)
245 {
246     struct stream *s;
247     char *data;
248     char *text;
249     char *name;
250     char *value;
251     char *lvalue;
252     int len;
253     int file_size;
254 
255     data = (char *) g_malloc(FILE_MAX_LINE_BYTES * 3, 0);
256     text = data;
257     name = text + FILE_MAX_LINE_BYTES;
258     value = name + FILE_MAX_LINE_BYTES;
259 
260     file_size = 32 * 1024; /* 32 K file size limit */
261     g_file_seek(fd, 0);
262     g_memset(text, 0, FILE_MAX_LINE_BYTES);
263     list_clear(names);
264     list_clear(values);
265     make_stream(s);
266     init_stream(s, file_size);
267     len = g_file_read(fd, s->data, file_size);
268 
269     if (len > 0)
270     {
271         s->end = s->p + len;
272         while (file_read_ini_line(s, text, FILE_MAX_LINE_BYTES) == 0)
273         {
274             if (line_lookup_for_section_name(text, FILE_MAX_LINE_BYTES) != 0)
275             {
276                 if (g_strcasecmp(section, text) == 0)
277                 {
278                     while (file_read_ini_line(s, text,
279                                               FILE_MAX_LINE_BYTES) == 0)
280                     {
281                         if (line_lookup_for_section_name(text, FILE_MAX_LINE_BYTES) != 0)
282                         {
283                             break;
284                         }
285 
286                         if (g_strlen(text) > 0)
287                         {
288                             file_split_name_value(text, name, value);
289                             list_add_item(names, (tbus)g_strdup(name));
290 
291                             if (value[0] == '$')
292                             {
293                                 lvalue = g_getenv(value + 1);
294 
295                                 if (lvalue != 0)
296                                 {
297                                     list_add_item(values, (tbus)g_strdup(lvalue));
298                                 }
299                                 else
300                                 {
301                                     list_add_item(values, (tbus)g_strdup(""));
302                                 }
303                             }
304                             else
305                             {
306                                 list_add_item(values, (tbus)g_strdup(value));
307                             }
308                         }
309                     }
310                     free_stream(s);
311                     g_free(data);
312                     return 0;
313                 }
314             }
315         }
316     }
317 
318     free_stream(s);
319     g_free(data);
320     return 1;
321 }
322 
323 /*****************************************************************************/
324 /* returns error
325    returns 0 if everything is ok
326    returns 1 if problem reading file */
327 /* 32 K file size limit */
328 int
file_read_sections(int fd,struct list * names)329 file_read_sections(int fd, struct list *names)
330 {
331     return l_file_read_sections(fd, 32 * 1024, names);
332 }
333 
334 /*****************************************************************************/
335 /* return error */
336 /* this function should be preferred over file_read_sections because it can
337    read any file size */
338 int
file_by_name_read_sections(const char * file_name,struct list * names)339 file_by_name_read_sections(const char *file_name, struct list *names)
340 {
341     int fd;
342     int file_size;
343     int rv;
344 
345     file_size = g_file_get_size(file_name);
346 
347     if (file_size < 1)
348     {
349         return 1;
350     }
351 
352     fd = g_file_open_ex(file_name, 1, 0, 0, 0);
353 
354     if (fd < 0)
355     {
356         return 1;
357     }
358 
359     rv = l_file_read_sections(fd, file_size, names);
360     g_file_close(fd);
361     return rv;
362 }
363 
364 /*****************************************************************************/
365 /* return error */
366 /* 32 K file size limit */
367 int
file_read_section(int fd,const char * section,struct list * names,struct list * values)368 file_read_section(int fd, const char *section,
369                   struct list *names, struct list *values)
370 {
371     return l_file_read_section(fd, 32 * 1024, section, names, values);
372 }
373 
374 /*****************************************************************************/
375 /* return error */
376 /* this function should be preferred over file_read_section because it can
377    read any file size */
378 int
file_by_name_read_section(const char * file_name,const char * section,struct list * names,struct list * values)379 file_by_name_read_section(const char *file_name, const char *section,
380                           struct list *names, struct list *values)
381 {
382     int fd;
383     int file_size;
384     int rv;
385 
386     file_size = g_file_get_size(file_name);
387 
388     if (file_size < 1)
389     {
390         return 1;
391     }
392 
393     fd = g_file_open_ex(file_name, 1, 0, 0, 0);
394 
395     if (fd < 0)
396     {
397         return 1;
398     }
399 
400     rv = l_file_read_section(fd, file_size, section, names, values);
401     g_file_close(fd);
402     return rv;
403 }
404