static int ipv6_parse_main(struct mystr* p_out_str, const struct mystr* p_in_str) { static struct mystr s_lhs_str; static struct mystr s_rhs_str; struct str_locate_result loc_ret; str_copy(&s_lhs_str, p_in_str); while (!str_isempty(&s_lhs_str)) { str_split_char(&s_lhs_str, &s_rhs_str, ':'); if (str_isempty(&s_lhs_str)) { return 0; } loc_ret = str_locate_char(&s_lhs_str, '.'); if (loc_ret.found) { if (!ipv4_parse_dotquad(p_out_str, &s_lhs_str)) { return 0; } } else if (!ipv6_parse_hex(p_out_str, &s_lhs_str)) { return 0; } str_copy(&s_lhs_str, &s_rhs_str); } return 1; }
static enum EVSFPrivopLoginResult handle_anonymous_login(struct vsf_session* p_sess, const struct mystr* p_pass_str) { if (!str_isempty(&p_sess->banned_email_str) && str_contains_line(&p_sess->banned_email_str, p_pass_str)) { return kVSFLoginFail; } if (!str_isempty(&p_sess->email_passwords_str) && (!str_contains_line(&p_sess->email_passwords_str, p_pass_str) || str_isempty(p_pass_str))) { return kVSFLoginFail; } /* Store the anonymous identity string */ str_copy(&p_sess->anon_pass_str, p_pass_str); if (str_isempty(&p_sess->anon_pass_str)) { str_alloc_text(&p_sess->anon_pass_str, "?"); } /* "Fix" any characters which might upset the log processing */ str_replace_char(&p_sess->anon_pass_str, ' ', '_'); str_replace_char(&p_sess->anon_pass_str, '\n', '?'); { struct mystr ftp_username_str = INIT_MYSTR; str_alloc_text(&ftp_username_str, tunable_ftp_username); setup_username_globals(p_sess, &ftp_username_str); str_free(&ftp_username_str); } str_free(&p_sess->banned_email_str); str_free(&p_sess->email_passwords_str); return kVSFLoginAnon; }
const unsigned char* vsf_sysutil_parse_uchar_string_sep( const struct mystr* p_str, char sep, unsigned char* p_items, unsigned int items) { static struct mystr s_tmp_str; unsigned int i; str_copy(&s_tmp_str, p_str); for (i=0; i<items; i++) { static struct mystr s_rhs_sep_str; int this_number; /* This puts a single separator delimited field in tmp_str */ str_split_char(&s_tmp_str, &s_rhs_sep_str, sep); /* Sanity - check for too many or two few dots! */ if ( (i < (items-1) && str_isempty(&s_rhs_sep_str)) || (i == (items-1) && !str_isempty(&s_rhs_sep_str))) { return 0; } this_number = str_atoi(&s_tmp_str); if (this_number < 0 || this_number > 255) { return 0; } /* If this truncates from int to uchar, we don't care */ p_items[i] = (unsigned char) this_number; /* The right hand side of the comma now becomes the new string to * breakdown */ str_copy(&s_tmp_str, &s_rhs_sep_str); } return p_items; }
static void handle_site_chmod(struct vsf_session* p_sess, struct mystr* p_arg_str) { static struct mystr s_chmod_file_str; unsigned int perms; int retval; if (str_isempty(p_arg_str)) { vsf_cmdio_write(p_sess, FTP_BADCMD, "SITE CHMOD needs 2 arguments."); return; } str_split_char(p_arg_str, &s_chmod_file_str, ' '); if (str_isempty(&s_chmod_file_str)) { vsf_cmdio_write(p_sess, FTP_BADCMD, "SITE CHMOD needs 2 arguments."); return; } /* Don't worry - our chmod() implementation only allows 0 - 0777 */ perms = str_octal_to_uint(p_arg_str); retval = str_chmod(&s_chmod_file_str, perms); if (vsf_sysutil_retval_is_error(retval)) { vsf_cmdio_write(p_sess, FTP_FILEFAIL, "SITE CHMOD command failed."); } else { vsf_cmdio_write(p_sess, FTP_CHMODOK, "SITE CHMOD command ok."); } }
static int sort_compare_common(const void* p1, const void* p2, int reverse) { const struct mystr* p_cmp1; const struct mystr* p_cmp2; const struct mystr_list_node* p_node1 = (const struct mystr_list_node*) p1; const struct mystr_list_node* p_node2 = (const struct mystr_list_node*) p2; if (!str_isempty(&p_node1->sort_key_str)) { p_cmp1 = &p_node1->sort_key_str; } else { p_cmp1 = &p_node1->str; } if (!str_isempty(&p_node2->sort_key_str)) { p_cmp2 = &p_node2->sort_key_str; } else { p_cmp2 = &p_node2->str; } if (reverse) { return str_strcmp(p_cmp2, p_cmp1); } else { return str_strcmp(p_cmp1, p_cmp2); } }
static void handle_port(struct vsf_session* p_sess) { static struct mystr s_tmp_str; unsigned short the_port; unsigned char vals[6]; int i; pasv_cleanup(p_sess); port_cleanup(p_sess); str_copy(&s_tmp_str, &p_sess->ftp_arg_str); for (i=0; i<6; i++) { static struct mystr s_rhs_comma_str; int this_number; /* This puts a single , delimited field in tmp_str */ str_split_char(&s_tmp_str, &s_rhs_comma_str, ','); /* Sanity - check for too many or two few commas! */ if ( (i<5 && str_isempty(&s_rhs_comma_str)) || (i==5 && !str_isempty(&s_rhs_comma_str))) { vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command."); return; } this_number = str_atoi(&s_tmp_str); if (this_number < 0 || this_number > 255) { vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command."); return; } /* If this truncates from int to uchar, we don't care */ vals[i] = (unsigned char) this_number; /* The right hand side of the comma now becomes the new string to * breakdown */ str_copy(&s_tmp_str, &s_rhs_comma_str); } the_port = vals[4] << 8; the_port |= vals[5]; vsf_sysutil_sockaddr_alloc_ipv4(&p_sess->p_port_sockaddr); vsf_sysutil_sockaddr_set_ipv4addr(p_sess->p_port_sockaddr, vals); vsf_sysutil_sockaddr_set_port(p_sess->p_port_sockaddr, the_port); /* SECURITY: * 1) Reject requests not connecting to the control socket IP * 2) Reject connects to privileged ports */ if (!tunable_port_promiscuous) { if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_sess->p_port_sockaddr) || vsf_sysutil_is_port_reserved(the_port)) { vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command."); port_cleanup(p_sess); return; } } vsf_cmdio_write(p_sess, FTP_PORTOK, "PORT command successful. Consider using PASV."); }
int str_path_isabs(const char *str) { int abs = 1; if (str_isempty(str)) return 0; if (*str != '/') return 0; strtok_t _st, *st = &_st, *p; if (!strtok_init_str(st, str, "/", 0)) return -1; strtok_for_each(st, p) { if (str_equal(p->token, ".") || str_equal(p->token, "..") || !str_isgraph(p->token)) { abs = 0; break; } } strtok_free(st); return abs; }
result_t cmp_anim_modify(struct cmp_obj* obj, struct allocator* alloc, struct allocator* tmp_alloc, void* data, cmphandle_t cur_hdl) { result_t r; struct cmp_anim* a = (struct cmp_anim*)data; uint filehash = hash_str(a->filepath); int reload = (a->filepathhash == filehash); cmp_anim_destroydata(obj, a, cur_hdl, !reload); a->filepathhash = filehash; a->alloc = alloc; if (str_isempty(a->filepath)) return RET_OK; if (!reload) a->clip_hdl = rs_load_animreel(a->filepath, 0); if (a->clip_hdl == INVALID_HANDLE) return RET_FAIL; /* bind */ r = cmp_anim_bind(obj, a, alloc, tmp_alloc, cur_hdl); if (IS_FAIL(r)) { err_sendtolog(TRUE); log_print(LOG_WARNING, "binding anim-set failed"); return RET_FAIL; } return RET_OK; }
int credentials_charset_is_valid(char *str_non_ascii) { char reject[] = " :@\"|\\/=+<>[]*?,;"; return str_isempty(str_non_ascii) || strcspn(str_non_ascii, reject) == strlen(str_non_ascii); }
int vsf_access_check_file_visible(const struct mystr* p_filename_str) { static struct mystr s_access_str; if (!tunable_hide_file) { return 1; } if (str_isempty(&s_access_str)) { str_alloc_text(&s_access_str, tunable_hide_file); } if (vsf_filename_passes_filter(p_filename_str, &s_access_str)) { return 0; } else { struct str_locate_result loc_res = str_locate_str(p_filename_str, &s_access_str); if (loc_res.found) { return 0; } } return 1; }
static void handle_pass_command(struct vsf_session* p_sess) { if (str_isempty(&p_sess->user_str)) { vsf_cmdio_write(p_sess, FTP_NEEDUSER, "Login with USER first."); return; } /* These login calls never return if successful */ if (tunable_one_process_model) { vsf_one_process_login(p_sess, &p_sess->ftp_arg_str); } else { vsf_two_process_login(p_sess, &p_sess->ftp_arg_str); } vsf_cmdio_write(p_sess, FTP_LOGINERR, "Login incorrect."); if (++p_sess->login_fails >= tunable_max_login_fails) { vsf_sysutil_exit(0); } str_empty(&p_sess->user_str); /* FALLTHRU if login fails */ }
static void handle_rnto(struct vsf_session* p_sess) { int retval; /* If we didn't get a RNFR, throw a wobbly */ if (str_isempty(&p_sess->rnfr_filename_str)) { vsf_cmdio_write(p_sess, FTP_NEEDRNFR, "RNFR required first."); return; } /* NOTE - might overwrite destination file. Not a concern because the same * could be accomplished with DELE. */ retval = str_rename(&p_sess->rnfr_filename_str, &p_sess->ftp_arg_str); /* Clear the RNFR filename; start the two stage process again! */ str_free(&p_sess->rnfr_filename_str); if (retval == 0) { vsf_cmdio_write(p_sess, FTP_RENAMEOK, "Rename successful."); } else { vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Rename failed."); } }
void vsf_cmdio_get_cmd_and_arg(struct vsf_session* p_sess, struct mystr* p_cmd_str, struct mystr* p_arg_str, int set_alarm) { /* Prepare an alarm to timeout the session.. */ if (set_alarm) { vsf_cmdio_set_alarm(p_sess); } /* Blocks */ control_getline(p_cmd_str, p_sess); str_split_char(p_cmd_str, p_arg_str, ' '); str_upper(p_cmd_str); if (tunable_log_ftp_protocol) { static struct mystr s_log_str; if (str_equal_text(p_cmd_str, "PASS")) { str_alloc_text(&s_log_str, "PASS <password>"); } else { str_copy(&s_log_str, p_cmd_str); if (!str_isempty(p_arg_str)) { str_append_char(&s_log_str, ' '); str_append_str(&s_log_str, p_arg_str); } } vsf_log_line(p_sess, kVSFLogEntryFTPInput, &s_log_str); } }
char *str_path_dirname(const char *path) { /* empty string or '..' */ if (str_isempty(path) || str_equal(path, "..")) return str_dup("."); /* skip prefixing '/' but preserve exactly one */ while (*path && *(path+1) && *path == '/' && *(path+1) == '/') path++; int found = 0; char *p, *buf = str_dup(path); while ((p = str_rchr(buf, '/', str_len(buf)))) { /* remove trailing slash */ if (p[1] == 0 && p != buf) *p = 0; /* no basename was found until yet */ else if (!found) { *p = 0; found = 1; } /* a basename was found and no trailing slash anymore */ else break; } char *dn; /* path consists only of basename and slashes */ if (str_isempty(buf)) dn = str_dup("/"); /* path is relative or absolute, basename was stripped */ else if (p) dn = str_dup(buf); /* path is relative, no basename was stripped */ else dn = str_dup("."); free(buf); return dn; }
static void handle_user_command(struct vsf_session* p_sess) { /* SECURITY: If we're in anonymous only-mode, immediately reject * non-anonymous usernames in the hope we save passwords going plaintext * over the network */ int is_anon = 1; str_copy(&p_sess->user_str, &p_sess->ftp_arg_str); str_upper(&p_sess->ftp_arg_str); if (!str_equal_text(&p_sess->ftp_arg_str, "FTP") && !str_equal_text(&p_sess->ftp_arg_str, "ANONYMOUS")) { is_anon = 0; } if (!tunable_local_enable && !is_anon) { vsf_cmdio_write( p_sess, FTP_LOGINERR, "This FTP server is anonymous only."); str_empty(&p_sess->user_str); return; } if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl) { vsf_cmdio_write( p_sess, FTP_LOGINERR, "Anonymous sessions may not use encryption."); str_empty(&p_sess->user_str); return; } if (tunable_ssl_enable && !is_anon && !p_sess->control_use_ssl && tunable_force_local_logins_ssl) { vsf_cmdio_write( p_sess, FTP_LOGINERR, "Non-anonymous sessions must use encryption."); str_empty(&p_sess->user_str); return; } if (!str_isempty(&p_sess->userlist_str)) { int located = str_contains_line(&p_sess->userlist_str, &p_sess->user_str); if ((located && tunable_userlist_deny) || (!located && !tunable_userlist_deny)) { vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied."); str_empty(&p_sess->user_str); return; } } if (is_anon && tunable_no_anon_password) { /* Fake a password */ str_alloc_text(&p_sess->ftp_arg_str, "<no password>"); handle_pass_command(p_sess); } else { vsf_cmdio_write(p_sess, FTP_GIVEPWORD, "Please specify the password."); } }
/* tests whether this is a valid phone number, digits and hyphen are allowed */ int str_is_phone_number(char *s) { /* TODO: Why not use str_re? */ if (str_isempty(s)) return 0; for (; isdigit((int)*s) || *s == '-'; s++); return !!*s; }
/* vg.remove(string group, string name) */ xmlrpc_value *m_vg_remove(xmlrpc_env *env, xmlrpc_value *p, void *c) { LOG_TRACEME xmlrpc_value *params; char *group, *name; int rc, gid = 0; xid_t xid; params = method_init(env, p, c, VCD_CAP_AUTH, 0); method_return_if_fault(env); xmlrpc_decompose_value(env, params, "{s:s,s:s,*}", "group", &group, "name", &name); method_return_if_fault(env); if (!validate_group(group)) method_return_faultf(env, MEINVAL, "invalid group value: %s", group); if (str_equal(group, "all")) method_return_faultf(env, MEINVAL, "cannot remove reserved group '%s'", group); if (!(gid = vxdb_getgid(group))) method_return_fault(env, MENOVG); if (!str_isempty(name)) { if (!validate_name(name)) method_return_faultf(env, MEINVAL, "invalid name value: %s", name); if (!(xid = vxdb_getxid(name))) method_return_fault(env, MENOVPS); rc = vxdb_exec( "DELETE FROM xid_gid_map WHERE xid = %d AND gid = %d", xid, gid); } else { rc = vxdb_exec( "BEGIN EXCLUSIVE TRANSACTION;" "DELETE FROM xid_gid_map WHERE gid = %d;" "DELETE FROM groups WHERE gid = %d;" "COMMIT TRANSACTION;", gid, gid); } if (rc != VXDB_OK) method_return_vxdb_fault(env); return xmlrpc_nil_new(env); }
struct h3d_anim_clip* import_loadclips(const char* json_filepath, uint frame_cnt, OUT uint* clip_cnt) { /* return default clips, which is the whole animation */ if (str_isempty(json_filepath)) { *clip_cnt = 1; return import_defaultclip(frame_cnt); } char* json_data = util_readtextfile(json_filepath, mem_heap()); if (json_data == NULL) { printf(TERM_BOLDYELLOW "Warning: could not open JSON file '%s' for clips," " reseting to default", json_filepath); *clip_cnt = 1; return import_defaultclip(frame_cnt); } json_t jroot = json_parsestring(json_data); FREE(json_data); if (jroot == NULL) { printf(TERM_BOLDYELLOW "Warning: could not read JSON file '%s' for clips," " reseting to default", json_filepath); *clip_cnt = 1; return import_defaultclip(frame_cnt); } /* */ json_t jclips = jroot; uint cnt = json_getarr_count(jclips); if (cnt == 0) { printf(TERM_BOLDYELLOW "Warning: no clip defined in JSON file '%s'," " switching to default", json_filepath); *clip_cnt = 1; return import_defaultclip(frame_cnt); } struct h3d_anim_clip* clips = (struct h3d_anim_clip*)ALLOC(sizeof(struct h3d_anim_clip)*cnt, 0); ASSERT(clips); for (uint i = 0; i < cnt; i++) { json_t jclip = json_getarr_item(jclips, i); strcpy(clips[i].name, json_gets_child(jclip, "name", "[noname]")); clips[i].start = minui(json_geti_child(jclip, "start", 0), frame_cnt-1); clips[i].end = minui(json_geti_child(jclip, "end", frame_cnt), frame_cnt); clips[i].looped = json_getb_child(jclip, "looped", FALSE); } json_destroy(jroot); *clip_cnt = cnt; return clips; }
void vsf_parseconf_load_file(const char* p_filename) { struct mystr config_file_str = INIT_MYSTR; struct mystr config_setting_str = INIT_MYSTR; struct mystr config_value_str = INIT_MYSTR; unsigned int str_pos = 0; int retval; if (!p_filename) { p_filename = s_p_saved_filename; } else { if (s_p_saved_filename) { vsf_sysutil_free((char*)s_p_saved_filename); } s_p_saved_filename = vsf_sysutil_strdup(p_filename); } if (!p_filename) { bug("null filename in vsf_parseconf_load_file"); } if (!s_strings_copied) { s_strings_copied = 1; /* A minor hack to make sure all strings are malloc()'ed so we can free * them at some later date. Specifically handles strings embedded in the * binary. */ copy_string_settings(); } retval = str_fileread(&config_file_str, p_filename, VSFTP_CONF_FILE_MAX); if (vsf_sysutil_retval_is_error(retval)) { die("cannot open config file"); } while (str_getline(&config_file_str, &config_setting_str, &str_pos)) { if (str_isempty(&config_setting_str) || str_get_char_at(&config_setting_str, 0) == '#') { continue; } /* Split into name=value pair */ str_split_char(&config_setting_str, &config_value_str, '='); handle_config_setting(&config_setting_str, &config_value_str); } str_free(&config_file_str); str_free(&config_setting_str); str_free(&config_value_str); }
static void prepend_path_to_filename(struct mystr* p_str) { static struct mystr s_tmp_str; /* Only prepend current working directory if the incoming filename is * relative */ str_empty(&s_tmp_str); if (str_isempty(p_str) || str_get_char_at(p_str, 0) != '/') { str_getcwd(&s_tmp_str); /* Careful to not emit // if we are in directory / (common with chroot) */ if (str_isempty(&s_tmp_str) || str_get_char_at(&s_tmp_str, str_getlen(&s_tmp_str) - 1) != '/') { str_append_char(&s_tmp_str, '/'); } } str_append_str(&s_tmp_str, p_str); str_copy(p_str, &s_tmp_str); }
void vsf_sysutil_setproctitle(const char* p_text) { struct mystr proctitle_str = INIT_MYSTR; str_copy(&proctitle_str, &s_proctitle_prefix_str); if (!str_isempty(&proctitle_str)) { str_append_text(&proctitle_str, ": "); } str_append_text(&proctitle_str, p_text); vsf_sysutil_setproctitle_internal(str_getbuf(&proctitle_str)); str_free(&proctitle_str); }
char *str_path_concat(const char *dirname, const char *basename) { char *path = 0; if (str_len(basename) > 1 && memcmp(basename, "./", 2) == 0) basename += 2; if (str_isempty(dirname) || str_path_isdot(basename)) return 0; _lucid_asprintf(&path, "%s/%s", dirname, basename); return path; }
static void emit_greeting(struct vsf_session* p_sess) { struct mystr str_log_line = INIT_MYSTR; /* Check for client limits (standalone mode only) */ if (tunable_max_clients > 0 && p_sess->num_clients > tunable_max_clients) { str_alloc_text(&str_log_line, "Connection refused: too many sessions."); vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line); vsf_cmdio_write_noblock(p_sess, FTP_TOO_MANY_USERS, "There are too many connected users, please try later."); vsf_sysutil_exit(0); } if (tunable_max_per_ip > 0 && p_sess->num_this_ip > tunable_max_per_ip) { str_alloc_text(&str_log_line, "Connection refused: too many sessions for this address."); vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line); vsf_cmdio_write_noblock(p_sess, FTP_IP_LIMIT, "There are too many connections from your internet address."); vsf_sysutil_exit(0); } if (!p_sess->tcp_wrapper_ok) { str_alloc_text(&str_log_line, "Connection refused: tcp_wrappers denial."); vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line); vsf_cmdio_write_noblock(p_sess, FTP_IP_DENY, "Service not available."); vsf_sysutil_exit(0); } vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line); if (!str_isempty(&p_sess->banner_str)) { vsf_banner_write(p_sess, &p_sess->banner_str, FTP_GREET); str_free(&p_sess->banner_str); vsf_cmdio_write(p_sess, FTP_GREET, ""); } else if (tunable_ftpd_banner == 0) { vsf_cmdio_write(p_sess, FTP_GREET, "(vsFTPd " VSF_VERSION ")"); } else { vsf_cmdio_write(p_sess, FTP_GREET, tunable_ftpd_banner); } }
static void emit_greeting(struct vsf_session* p_sess) { if (!str_isempty(&p_sess->banner_str)) { vsf_banner_write(p_sess, &p_sess->banner_str, FTP_GREET); str_free(&p_sess->banner_str); vsf_cmdio_write(p_sess, FTP_GREET, ""); } else if (tunable_ftpd_banner == 0) { vsf_cmdio_write(p_sess, FTP_GREET, "(vsFTPd " VSF_VERSION ")"); } else { vsf_cmdio_write(p_sess, FTP_GREET, tunable_ftpd_banner); } }
void vsf_cmdio_get_cmd_and_arg(struct vsf_session* p_sess, struct mystr* p_cmd_str, struct mystr* p_arg_str, int set_alarm) { /* Prepare an alarm to timeout the session.. */ if (set_alarm) { vsf_cmdio_set_alarm(p_sess); } /* Blocks */ control_getline(p_cmd_str, p_sess); /* View a single space as a command of " ", which although a useless command, * permits the caller to distinguish input of "" from " ". */ if (str_getlen(p_cmd_str) == 1 && str_get_char_at(p_cmd_str, 0) == ' ') { str_empty(p_arg_str); } else { str_split_char(p_cmd_str, p_arg_str, ' '); } str_upper(p_cmd_str); if (tunable_log_ftp_protocol) { static struct mystr s_log_str; if (str_equal_text(p_cmd_str, "PASS")) { str_alloc_text(&s_log_str, "PASS <password>"); } else { str_copy(&s_log_str, p_cmd_str); if (!str_isempty(p_arg_str)) { str_append_char(&s_log_str, ' '); str_append_str(&s_log_str, p_arg_str); } } vsf_log_line(p_sess, kVSFLogEntryFTPInput, &s_log_str); } }
char *str_path_basename(const char *path) { /* empty string */ if (str_isempty(path)) return str_dup("."); /* skip prefixing '/' */ while (*path && *path == '/') path++; /* string consisting entirely of '/' */ if (!*path) return str_dup("/"); char *p, *buf = str_dup(path); while ((p = str_rchr(buf, '/', str_len(buf)))) { /* remove trailing lash */ if (p[1] == 0 && p != buf) *p = 0; /* no trailing slash anymore */ else break; } char *bn; /* if a non-trailing slash was found, return everything after it */ if (p) bn = str_dup(p + 1); /* otherwise buf already contains basename */ else bn = str_dup(buf); free(buf); return bn; }
static void handle_site_umask(struct vsf_session* p_sess, struct mystr* p_arg_str) { static struct mystr s_umask_resp_str; if (str_isempty(p_arg_str)) { /* Empty arg => report current umask */ str_alloc_text(&s_umask_resp_str, "Your current UMASK is "); str_append_text(&s_umask_resp_str, vsf_sysutil_uint_to_octal(vsf_sysutil_get_umask())); } else { /* Set current umask */ unsigned int new_umask = str_octal_to_uint(p_arg_str); vsf_sysutil_set_umask(new_umask); str_alloc_text(&s_umask_resp_str, "UMASK set to "); str_append_text(&s_umask_resp_str, vsf_sysutil_uint_to_octal(vsf_sysutil_get_umask())); } vsf_cmdio_write_str(p_sess, FTP_UMASKOK, &s_umask_resp_str); }
void str_replace_text(struct mystr* p_str, const char* p_from, const char* p_to) { static struct mystr s_lhs_chunk_str; static struct mystr s_rhs_chunk_str; unsigned int lhs_len; str_copy(&s_lhs_chunk_str, p_str); str_free(p_str); do { lhs_len = str_getlen(&s_lhs_chunk_str); str_split_text(&s_lhs_chunk_str, &s_rhs_chunk_str, p_from); /* Copy lhs to destination */ str_append_str(p_str, &s_lhs_chunk_str); /* If this was a 'hit', append the 'to' text */ if (str_getlen(&s_lhs_chunk_str) < lhs_len) { str_append_text(p_str, p_to); } /* Current rhs becomes new lhs */ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str); } while (!str_isempty(&s_lhs_chunk_str)); }
int str_path_isdot(const char *str) { int found = 0; if (str_isempty(str)) return 0; strtok_t _st, *st = &_st, *p; if (!strtok_init_str(st, str, "/", 0)) return 0; strtok_for_each(st, p) { if (str_equal(p->token, ".") || str_equal(p->token, "..")) { found = 1; break; } } strtok_free(st); return found; }
void vsf_one_process_start(struct vsf_session* p_sess) { unsigned int caps = 0; if (tunable_chown_uploads) { caps |= kCapabilityCAP_CHOWN; } if (tunable_connect_from_port_20) { caps |= kCapabilityCAP_NET_BIND_SERVICE; } { struct mystr user_name = INIT_MYSTR; struct mystr chdir_str = INIT_MYSTR; str_alloc_text(&user_name, tunable_ftp_username); if (tunable_anon_root) { str_alloc_text(&chdir_str, tunable_anon_root); } if (tunable_run_as_launching_user) { if (!str_isempty(&chdir_str)) { (void) str_chdir(&chdir_str); } } else { vsf_secutil_change_credentials(&user_name, 0, &chdir_str, caps, VSF_SECUTIL_OPTION_CHROOT | VSF_SECUTIL_OPTION_USE_GROUPS); } str_free(&user_name); str_free(&chdir_str); } init_connection(p_sess); }