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 ∅ 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