1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <grp.h>
5#include <unistd.h>
6
7#include "options.h"
8#include "mystring.h"
9#include "main.h"
10#include "login.h"
11#include "logging.h"
12
13struct global config_global;
14struct group_of_users *config_groups;
15struct user *config_users;
16
17int readyshareCloud_conn = 0;	/* pling added 10/08/2012 */
18
19/*
20Returns NULL on error. May return
21emtpy string "" for empty or
22commented lines.
23*/
24char *config_read_line(FILE *configfile)
25{
26	static char str[256];
27	char *s = str;
28	if (!fgets(str, sizeof(str), configfile))
29		return NULL;
30	while ((strchr(s, '#') > strchr(s, '"')) && strchr(s, '"')) {
31		s = strchr(strchr(s, '"') + 1, '"');
32		if (!s) { // This means there is only one " in the string, which is a syntax error.
33			str[0] = 0; // So we empty the string in order not to confuse the parser.
34			return str;
35		}
36	}
37	if (strchr(s, '#'))
38		*strchr(s, '#') = 0;
39	s = str;
40	while ((s[0] == ' ') || (s[0] == '\t'))
41		s++;
42	return s;
43}
44
45void create_options(FILE *configfile, struct bftpd_option **options, struct directory **directories)
46{
47    char *str;
48    struct bftpd_option *opt = NULL;
49    struct directory *dir = NULL;
50	str = config_read_line(configfile);
51	while (!strchr(str, '}')) {
52  		if (str[0] != '\n') {
53            if ((strstr(str, "directory")) && (strchr(str, '{')) && (directories)) {
54                char *tmp;
55                if (dir) {
56                    dir = dir->next = malloc(sizeof(struct directory));
57                } else {
58                    *directories = dir = malloc(sizeof(struct directory));
59                }
60                tmp = strchr(str, '"') + 1;
61                *strchr(tmp, '"') = 0;
62                dir->path = strdup(tmp);
63                create_options(configfile, &(dir->options), NULL);
64            } else {
65       			if (opt) {
66       				opt = opt->next = malloc(sizeof(struct bftpd_option));
67       			} else {
68       				*options = opt = malloc(sizeof(struct bftpd_option));
69       			}
70       			opt->name = (char *) malloc(strlen(str));
71       			// opt->value = (char *) malloc(strlen(str));
72                        opt->value = (char *) malloc( strlen(str) + 256);
73       			sscanf(str, "%[^=]=\"%[^\n\"]", opt->name, opt->value);
74            }
75   		}
76		str = config_read_line(configfile);
77	}
78}
79
80void expand_groups()
81{
82    char foo[USERLEN + 1];
83    struct passwd *temp;
84    struct group_of_users *grp;
85    struct group *grpinfo;
86    struct list_of_struct_passwd *endp = NULL;
87    struct list_of_struct_group *endg = NULL;
88    uid_t uid;
89    int i;
90    if ((grp = config_groups)) {
91        do {
92            strcat(grp->temp_members, ",");
93            while (strchr(grp->temp_members, ',')) {
94                sscanf(grp->temp_members, "%[^,]", foo);
95                cutto(grp->temp_members, strlen(foo) + 1);
96                if (foo[0] == '@') {
97                    if (sscanf(foo + 1, "%i", &uid)) {
98                        if (!((grpinfo = getgrgid(uid))))
99                            continue;
100                    } else
101                        if (!((grpinfo = getgrnam(foo + 1))))
102                            continue;
103                    if (grp->groups)
104                        endg = endg->next = malloc(sizeof(struct list_of_struct_group));
105                    else
106                        grp->groups = endg = malloc(sizeof(struct list_of_struct_group));
107                    endg->grp.gr_name = strdup(grpinfo->gr_name);
108                    endg->grp.gr_passwd = strdup(grpinfo->gr_passwd);
109                    endg->grp.gr_gid = grpinfo->gr_gid;
110                    for (i = 0; grpinfo->gr_mem[i]; i++);
111                    endg->grp.gr_mem = malloc((i + 1) * sizeof(char *));
112                    for (i = 0; grpinfo->gr_mem[i]; i++)
113                        endg->grp.gr_mem[i] = strdup(grpinfo->gr_mem[i]);
114                    endg->grp.gr_mem[i] = NULL;
115                }
116                if (sscanf(foo, "%i", &uid)) {
117                    if (!((temp = getpwuid(uid))))
118                        continue;
119                } else
120                    if (!((temp = getpwnam(foo))))
121                        continue;
122                if (grp->users)
123                    endp = endp->next = malloc(sizeof(struct list_of_struct_passwd));
124                else
125                    grp->users = endp = malloc(sizeof(struct list_of_struct_passwd));
126                /* This is ugly, but you can't just use memcpy()! */
127                endp->pwd.pw_name = strdup(temp->pw_name);
128                endp->pwd.pw_passwd = strdup(temp->pw_passwd);
129                endp->pwd.pw_uid = temp->pw_uid;
130                endp->pwd.pw_gid = temp->pw_gid;
131                endp->pwd.pw_gecos = strdup(temp->pw_gecos);
132                endp->pwd.pw_dir = strdup(temp->pw_dir);
133                endp->pwd.pw_shell = strdup(temp->pw_shell);
134            }
135            free(grp->temp_members);
136        } while ((grp = grp->next));
137    }
138}
139
140void config_init()
141{
142	FILE *configfile;
143	char *str;
144    struct group_of_users *grp = NULL;
145    struct user *usr = NULL;
146    config_global.options = NULL;
147    config_global.directories = NULL;
148	if (!configpath)
149		return;
150	configfile = fopen(configpath, "r");
151	if (!configfile) {
152		control_printf(SL_FAILURE, "421 Unable to open configuration file.");
153		exit(1);
154	}
155	/* Foxconn added start pling 10/08/2012 */
156	/* Handle ReadyShare Cloud connections specially */
157	if (strstr(configpath, "rscloud"))
158		readyshareCloud_conn = 1;
159	/* Foxconn added end pling 10/08/2012 */
160	while ((str = config_read_line(configfile))) {
161		if (strchr(str, '{')) {
162            replace(str, " {", "{");
163            replace(str, "{ ", "{");
164            replace(str, " }", "}");
165            replace(str, "} ", "}");
166            if (!strcasecmp(str, "global{\n")) {
167                create_options(configfile, &(config_global.options), &(config_global.directories));
168            } else if (strstr(str, "user ") == str) {
169                if (usr) {
170                    usr = usr->next = malloc(sizeof(struct user));
171                } else {
172                    config_users = usr = malloc(sizeof(struct user));
173                }
174                usr->name = strdup(str + 5);
175                *strchr(usr->name, '{') = 0;
176                create_options(configfile, &(usr->options), &(usr->directories));
177            } else if (strstr(str, "group ") == str) {
178                if (grp) {
179                    grp = grp->next = malloc(sizeof(struct group_of_users));
180                } else {
181                    config_groups = grp = malloc(sizeof(struct group_of_users));
182                }
183                cutto(str, 6);
184                *strchr(str, '{') = 0;
185                grp->users = NULL;
186                grp->next = NULL;
187                grp->temp_members = strdup(str);
188                create_options(configfile, &(grp->options), &(grp->directories));
189            }
190		}
191	}
192	fclose(configfile);
193}
194
195char *getoption(struct bftpd_option *opt, char *name)
196{
197	if (!opt)
198		return NULL;
199	do {
200		if (!strcasecmp(opt->name, name))
201			return opt->value;
202	} while ((opt = opt->next));
203    return NULL;
204}
205
206char *getoption_directories(struct directory *dir, char *name) {
207    char curpath[256], *bar;
208    struct directory *longest = NULL;
209    if(!dir)
210        return NULL;
211    getcwd(curpath, sizeof(curpath) - 1);
212    strcat(curpath, "/");
213    do {
214        bar = malloc(strlen(dir->path) + 2);
215        strcpy(bar, dir->path);
216        strcat(bar, "/");
217        if (!strncmp(curpath, bar, strlen(bar))) {
218            if (longest) {
219                if ((strlen(bar) > strlen(longest->path) + 1)
220                    && (getoption(dir->options, name)))
221                    longest = dir;
222            } else {
223                if (getoption(dir->options, name))
224                    longest = dir;
225            }
226        }
227        free(bar);
228    } while ((dir = dir->next));
229    if (longest)
230        return getoption(longest->options, name);
231    return NULL;
232}
233
234char user_is_in_group(struct group_of_users *grp) {
235    struct list_of_struct_group *grplist = grp->groups;
236    struct list_of_struct_passwd *pwdlist = grp->users;
237    int i;
238    if (pwdlist) {
239        do {
240            if (!strcmp(user, pwdlist->pwd.pw_name))
241                return 1;
242        } while ((pwdlist = pwdlist->next));
243    }
244    if (grplist) {
245        do {
246            if (userinfo.pw_gid == grplist->grp.gr_gid)
247                return 1;
248            for (i = 0; grplist->grp.gr_mem[i]; i++)
249                if (!strcmp(grplist->grp.gr_mem[i], user))
250                    return 1;
251        } while ((grplist = grplist->next));
252    }
253    return 0;
254}
255
256char *getoption_group(char *name)
257{
258    char *result;
259    struct group_of_users *grp;
260    if ((grp = config_groups)) {
261        do {
262            if (user_is_in_group(grp) && grp->options) {
263                if ((result = getoption_directories(grp->directories, name)))
264                    return result;
265                if ((result = getoption(grp->options, name)))
266                    return result;
267            }
268        } while ((grp = grp->next));
269    }
270    return NULL;
271}
272
273char *getoption_user(char *name)
274{
275    char *result;
276    struct user *usr;
277    if ((usr = config_users)) {
278        do {
279            if (!strcmp(user, usr->name)) {
280                if ((result = getoption_directories(usr->directories, name)))
281                    return result;
282                if ((result = getoption(usr->options, name)))
283                    return result;
284            }
285        } while ((usr = usr->next));
286    }
287    return NULL;
288}
289
290char *getoption_global(char *name)
291{
292    char *result;
293    if ((result = getoption_directories(config_global.directories, name)))
294        return result;
295    if (config_global.options) {
296        if ((result = getoption(config_global.options, name)))
297            return result;
298    }
299    return NULL;
300}
301
302
303/* returns null string on falure or pointer to value */
304char *config_getoption(char *name)
305{
306    static char empty = 0;
307//    char *result;
308	char *foo;
309    if (userinfo_set) {
310        if ((foo = getoption_user(name)))
311            return foo;
312        if ((foo = getoption_group(name)))
313            return foo;
314    }
315    if ((foo = getoption_global(name)))
316        return foo;
317    else
318        return &empty;
319}
320
321void config_end()
322{
323    /* Needn't do anything ATM */
324}
325
326
327
328/*
329This function attempts to find a option, stored
330in memory, by the given name. It searches
331global options first, then group options and,
332finally, individual user options. If a value
333is found for the option, the function returns
334a pointer to the value of the option. If no match
335is found, an empty string is returned.
336-- Jesse
337*/
338char *config_getoption_reread(char *find_me)
339{
340    char *return_value;
341    static char empty_string = 0;
342
343    return_value = getoption(config_global.options, find_me);
344    if (return_value)
345       return return_value;
346
347    return &empty_string;
348}
349
350
351
352/*
353This function opens the config file and
354tries to reset some of the option values
355in memory.
356-- Jesse
357*/
358void Reread_Config_File()
359{
360    char *line;     // line in config file
361    char *config_value;    // value stored in memory
362    char *new_value;
363    FILE *config_file;
364    int xfer_delay;
365    int section = 0;     // where are we in the config file
366
367    // open config file
368    config_file = fopen(configpath, "r");
369    if (! config_file)
370       return;
371
372    /* read a line from the config file */
373    line = config_read_line(config_file);
374    while ( line )
375    {
376       if ( strchr(line, '{') )
377          section++;
378
379       /* look for reconized option name */
380       if ( strstr(line, "HELLO_STRING") )
381          config_value = config_getoption_reread("HELLO_STRING");
382       else if ( strstr(line, "QUIT_MSG") )
383          config_value = config_getoption_reread("QUIT_MSG");
384       else if ( strstr(line, "XFERBUFSIZE") )
385          config_value = config_getoption_reread("XFERBUFSIZE");
386       else if ( strstr(line, "DATA_TIMEOUT") )
387          config_value = config_getoption_reread("DATA_TIMEOUT");
388       else if ( strstr(line, "CONTROL_TIMEOUT") )
389          config_value = config_getoption_reread("CONTROL_TIMEOUT");
390       else if ( strstr(line, "USERLIMIT_GLOBAL") )
391          config_value = config_getoption_reread("USERLIMIT_GLOBAL");
392       else if ( strstr(line, "USERLIMIT_SINGLEUSER") )
393          config_value = config_getoption_reread("USERLIMIT_SINGLEUSER");
394       else if ( strstr(line, "USERLIMIT_HOST") )
395          config_value = config_getoption_reread("USERLIMIT_HOST");
396       else if ( strstr(line, "DENY_LOGIN") )
397          config_value = config_getoption_reread("DENY_LOGIN");
398       else if ( strstr(line, "XFER_DELAY") )
399          config_value = config_getoption_reread("XFER_DELAY");
400       else if ( strstr(line, "GZ_UPLOAD") )
401          config_value = config_getoption_reread("GZ_UPLOAD");
402       else
403          config_value = NULL;
404
405       /* get new value from input */
406       new_value = strchr(line, '"') ;
407       if (new_value)
408       {
409           char *temp;
410           new_value++;      // go to first character after quote
411           temp = strchr(new_value, '"');
412           if (temp)
413              temp[0] = '\0';    // null terminal string
414       }
415
416       /* set value of option */
417       if ( (config_value) && (new_value) && (section == 1) )
418       {
419           // make sure it will fit.
420           if ( strlen(new_value) < 256)
421              strcpy(config_value, new_value);
422       }
423
424       line = config_read_line(config_file);
425    }       /* while not end of file */
426
427    fclose(config_file);
428
429    /* reset numeric values */
430    xfer_bufsize = strtoul( config_getoption("XFERBUFSIZE"), NULL, 0 );
431    if (! xfer_bufsize )
432       xfer_bufsize = XFER_BUFSIZE;
433
434    control_timeout = atoi( config_getoption("CONTROL_TIMEOUT") );
435    if (! control_timeout)
436       control_timeout = CONTROL_TIMEOUT;
437
438    data_timeout = atoi( config_getoption("DATA_TIMEOUT") );
439    if (! data_timeout)
440       data_timeout = DATA_TIMEOUT;
441
442    xfer_delay = atoi( config_getoption("XFER_DELAY") );
443}
444/* end of re-read config file */
445
446
447