void query_one_hostname(){ smb_srv_info_t *p; int bchange = 0; for (p = smb_srv_info_list; p; p = p->next) { if(is_shutdown) break; char* hostname = smbc_nmblookup(p->ip->ptr); if( strcmp(p->name->ptr, "")!=0&& hostname!=NULL && strcmp(p->name->ptr, hostname)==0 && p->online ==1 ){ if(hostname){ free(hostname); hostname=NULL; } continue; } if(hostname==NULL){ if(p->online==1){ p->online = 0; bchange = 1; Cdbg(DBE, "Can't query samba server name, set ip=[%s] offline", p->ip->ptr); } } else{ p->online = 1; buffer_reset(p->name); buffer_copy_string(p->name, hostname); bchange = 1; Cdbg(DBE, "query samba server name[%s], set ip=[%s] online", hostname, p->ip->ptr ); } if(bchange==1) save_arpping_list(); if(hostname){ free(hostname); hostname=NULL; } } //if(bchange==1) // save_arpping_list(); }
int openRawSocket (int *s, u_short type) { int optval = 1; if((*s = socket (AF_INET, SOCK_PACKET, htons (type))) == -1) { Cdbg(DBE, "Could not open raw socket\n"); return -1; } if(setsockopt (*s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof (optval)) == -1) { Cdbg(DBE, "Could not setsocketopt on raw socket\n"); return -1; } return 0; }
int nvram_smbdav_pc_append(const char* ap_str ) { char* nv_var_val=NULL; Cdbg(1,"call nvram_get"); if( !( nv_var_val = nvram_get(WEBDAV_SMB_PC)) ){ Cdbg(1,"nv_var get null"); return -1; } char tmp_nv_var_val[120]={0}; strcpy(tmp_nv_var_val, nv_var_val); strcat(tmp_nv_var_val, ap_str); nvram_set(WEBDAV_SMB_PC, tmp_nv_var_val); // char * test_str = nvram_get(nv_var); return 0; }
void query_one_hostname(){ smb_srv_info_t *p; for (p = smb_srv_info_list; p; p = p->next) { if(strcmp(p->name->ptr, "")!=0){ continue; } if(p->id==0){ Cdbg(DBE, "query_one_hostname [%s]\n", p->ip->ptr); //continue; } char* hostname = smbc_nmblookup(p->ip->ptr); if(hostname==NULL){ //Cdbg(DBE, "\t\tCan't query samba server name[%s]\n", p->ip->ptr); buffer_free(p->ip); buffer_free(p->mac); buffer_free(p->name); DLIST_REMOVE(smb_srv_info_list, p); free(p); } else{ buffer_copy_string(p->name, hostname); } } }
int in_the_same_folder(buffer *src, buffer *dst) { char *sp; char *smem = (char *)malloc(src->used); memcpy(smem, src->ptr, src->used); char *dmem = (char *)malloc(dst->used); memcpy(dmem, dst->ptr, dst->used); sp = strrchr(smem, '/'); int slen = sp - smem; sp = strrchr(dmem, '/'); int dlen = sp - dmem; smem[slen] = '\0'; dmem[dlen] = '\0'; int res = memcmp(smem, dmem, (slen>dlen) ? slen : dlen); Cdbg(DBE, "smem=%s,dmem=%s, slen=%d, dlen=%d", smem, dmem, slen, dlen); free(smem); free(dmem); return (res) ? 0 : 1; }
void on_arpping_timer_handler2(time_t cur_time) { if(g_bInitialize==0) return; thread_arpping(g_scan_interface); query_one_hostname(); //- Rescan samba server if( g_current_time > RE_SCAN_TIME_INTERVAL && g_threadIndex == MAX_THREADS ){ g_rescancount++; g_threadIndex = THREAD_BEGIN_INDEX;; char strTime[9] = {0}; strftime(strTime, sizeof(strTime), "%T", localtime(&cur_time)); Cdbg(DBE, "start to rescan samba server count=[%d], time_offset=[%d], time=[%s]\n", g_rescancount, g_current_time, strTime); g_current_time = 0; g_begin_time = 0; init_a_srvInfo(); } if(g_useSystemTimer==1){ if(g_begin_time==0) g_begin_time = cur_time; else g_current_time = cur_time - g_begin_time; } else{ g_current_time += ARP_TIME_INTERVAL; } }
void save_arpping_list(void) { #if EMBEDDED_EANBLE smb_srv_info_t* c; buffer* smbdav_list = buffer_init(); buffer_copy_string(smbdav_list, ""); for (c = smb_srv_info_list; c; c = c->next) { if(c->name->used == 0 || strcmp(c->name->ptr,"")==0) continue; char temp[50]="\0"; sprintf(temp, "%s<%s<%s<%d>", c->name->ptr, c->ip->ptr, c->mac->ptr, c->online); buffer_append_string(smbdav_list, temp); } Cdbg(DBE, "nvram_set_smbdav_str %s", smbdav_list->ptr); nvram_set_smbdav_str(smbdav_list->ptr); buffer_free(smbdav_list); #else unlink(g_temp_file); smb_srv_info_t* c; char mybuffer[100]; FILE* fp = fopen(g_temp_file, "w"); Cdbg(DBE, "save_arpping_list %s", g_temp_file); if(fp!=NULL){ smb_srv_info_t* c; for (c = smb_srv_info_list; c; c = c->next) { if(c->name->used == 0 || strcmp(c->name->ptr,"")==0) continue; fprintf(fp, "%s<%s<%s<%d\n", c->name->ptr, c->ip->ptr, c->mac->ptr, c->online); } fclose(fp); } #endif }
int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) { chunkqueue *cq; if (!con) return -1; Cdbg(DBE, "enter http_chunk_append_file..with fd=[%d], fn=[%s], offset=[%d], len=[%d]", con->fd, fn->ptr, offset, len); cq = con->write_queue; if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { http_chunk_append_len(srv, con, len); } chunkqueue_append_file(cq, fn, offset, len); if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) { chunkqueue_append_mem(cq, "\r\n", 2 + 1); } Cdbg(DBE, "leave"); return 0; }
void start_scan_sambaserver(int use_sys_timer) { Cdbg(DBE, "start start_scan_sambaserver..."); //- Remove all smb_srv_info_t *c; for (c = smb_srv_info_list; c; c = c->next) { Cdbg(DBE, "remove , ip=[%s]\n", c->ip->ptr); DLIST_REMOVE(smb_srv_info_list,c); free(c); c = smb_srv_info_list; } free(smb_srv_info_list); read_arpping_list(); if( init_a_srvInfo() == 0 ) return; g_useSystemTimer = use_sys_timer; g_bInitialize = 1; #ifdef _USEMYTIMER if(g_useSystemTimer==0){ g_arp_timer = create_timer(TT_SIGUSR2); install_sighandler(TT_SIGUSR2, on_arpping_timer_handler2); set_timer(g_arp_timer, ARP_TIME_INTERVAL); } #endif #ifdef _USEMYTIMER2 struct itimerval tout_val; tout_val.it_interval.tv_sec = ARP_TIME_INTERVAL; tout_val.it_interval.tv_usec = 0; tout_val.it_value.tv_sec = ARP_TIME_INTERVAL; /* set timer for "INTERVAL (10) seconds */ tout_val.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &tout_val,0); signal(SIGALRM,on_arpping_timer_handler2); /* set the Alarm signal capture */ #endif }
int nvram_is_ddns_enable() { char* ddns_e=NULL; int ddns_enable_x=0; if( (ddns_e = nvram_get(DDNS_ENANBLE_X))!=NULL ){ ddns_enable_x = atoi(ddns_e); Cdbg(DBE," ddns_e = %s", ddns_e); } if(ddns_enable_x) return 1; else return 0; }
void smbc_wrapper_response_401(server *srv, connection *con) { data_string *ds = (data_string *)array_get_element(con->request.headers, "user-Agent"); //- Browser response if( ds && (strstr( ds->value->ptr, "Mozilla" )||strstr( ds->value->ptr, "Opera" )) ){ if(con->mode == SMB_BASIC||con->mode == DIRECT){ Cdbg(DBE, "con->mode == SMB_BASIC -> return 401"); con->http_status = 401; return; } } Cdbg(DBE, "smbc_wrapper_response_401 -> return 401"); char str[50]; UNUSED(srv); buffer* tmp_buf = buffer_init(); if(con->mode == SMB_BASIC){ //sprintf(str, "Basic realm=\"%s\"", "smbdav"); if(con->smb_info&&con->smb_info->server->used) sprintf(str, "Basic realm=\"smb://%s\"", con->smb_info->server->ptr); else sprintf(str, "Basic realm=\"%s\"", "webdav"); } else if(con->mode == SMB_NTLM) sprintf(str, "NTLM"); else sprintf(str, "Basic realm=\"%s\"", "webdav"); buffer_copy_string(tmp_buf, str); response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(tmp_buf)); con->http_status = 401; buffer_free(tmp_buf); }
int network_register_fdevents(server *srv) { size_t i; if (-1 == fdevent_reset(srv->ev)) { return -1; } /* register fdevents after reset */ for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; Cdbg(DBE, "network_register_fdevents..[%d]: fd=[%d]\n", i, srv_socket->fd); fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket); fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); } return 0; }
char* nvram_get_ddns_host_name() { /* nvram get/set ddns_enable_x nvram get/set ddns_server_x (WWW.ASUS.COM) nvram get/set ddns_hostname_x (RT-N66U-00E012112233.asuscomm.com) rc rc_service restart_ddns or notify_rc(?œrestart_ddns?? through libshared */ char* ddns_host_name_x=NULL; if(!nvram_is_ddns_enable()) goto nvram_get_ddns_host_name_EXIT; if(!nvram_get_ddns_server_name) goto nvram_get_ddns_host_name_EXIT; ddns_host_name_x= nvram_get (DDNS_HOST_NAME_X); nvram_get_ddns_host_name_EXIT: Cdbg(DBE,"ddns_hostname_x = %s", ddns_host_name_x); return ddns_host_name_x; }
void stop_arpping_process() { /* char mybuffer[BUFSIZ]="\0"; char cmd[BUFSIZ]="\0"; int chars_read; FILE* read_fp = popen("pidof lighttpd-arpping", "r"); if(read_fp!=NULL){ chars_read = fread(mybuffer, sizeof(char), BUFSIZ, read_fp); if(chars_read>0){ sprintf(cmd, "kill -9 %s", mybuffer); Cdbg(DBE, "%s", cmd); system(cmd); } pclose(read_fp); } */ FILE *fp; char buf[256]; pid_t pid = 0; int n; if ((fp = fopen("/tmp/lighttpd/lighttpd-arpping.pid", "r")) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) pid = strtoul(buf, NULL, 0); fclose(fp); } if (pid > 1 && kill(pid, SIGTERM) == 0) { n = 10; while ((kill(pid, SIGTERM) == 0) && (n-- > 0)) { Cdbg(DBE,"Mod_smbdav: %s: waiting pid=%d n=%d\n", __FUNCTION__, pid, n); usleep(100 * 1000); } } unlink("/tmp/lighttpd/lighttpd-arpping.pid"); }
void stop_arpping_process() { FILE *fp; char buf[256]; pid_t pid = 0; int n; if ((fp = fopen(LIGHTTPD_ARPPING_PID_FILE_PATH, "r")) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) pid = strtoul(buf, NULL, 0); fclose(fp); } if (pid > 1 && kill(pid, SIGTERM) == 0) { n = 10; while ((kill(pid, SIGTERM) == 0) && (n-- > 0)) { Cdbg(DBE,"Mod_smbdav: %s: waiting pid=%d n=%d\n", __FUNCTION__, pid, n); usleep(100 * 1000); } } unlink(LIGHTTPD_ARPPING_PID_FILE_PATH); }
static void sigaction_handler(int sig, siginfo_t *si, void *context) { static siginfo_t empty_siginfo; UNUSED(context); if (!si) si = &empty_siginfo; switch (sig) { case SIGTERM:{ #if XXEMBEDDED_EANBLE int i, act; for (i = 30; i > 0; --i) { if (((act = check_action()) == ACT_IDLE) || (act == ACT_REBOOT)) break; fprintf(stderr, "Busy with %d. Waiting before shutdown... %d", act, i); sleep(1); } nvram_do_commit(); #endif Cdbg(DBE, "Shut down arpping....SIGTERM"); is_shutdown = 1; break; } case SIGINT: break; case SIGALRM: break; case SIGHUP: break; case SIGCHLD: break; case SIGUSR1: //- Remove all g_kill_list = 1; break; } }
static void chunk_reset(chunk *c) { if (NULL == c) return; c->type = MEM_CHUNK; buffer_reset(c->mem); if (c->file.is_temp && !buffer_string_is_empty(c->file.name)) { unlink(c->file.name->ptr); } buffer_reset(c->file.name); if(c->type == SMB_CHUNK){ if (c->file.fd != -1) { smbc_close(c->file.fd); Cdbg(DBE,"close smb file-------------------------------->remote computer"); c->file.fd = -1; } } else{ if (c->file.fd != -1) { close(c->file.fd); c->file.fd = -1; } if (MAP_FAILED != c->file.mmap.start) { munmap(c->file.mmap.start, c->file.mmap.length); c->file.mmap.start = MAP_FAILED; } } c->file.start = c->file.length = c->file.mmap.offset = 0; c->file.mmap.length = 0; c->file.is_temp = 0; c->offset = 0; c->next = NULL; }
int smbc_get_usbdisk_permission(const char* user_name, const char* usbdisk_rel_sub_path, const char* usbdisk_sub_share_folder) { int permission = -1; #if EMBEDDED_EANBLE int st_samba_mode = nvram_get_st_samba_mode(); if( (st_samba_mode==1) || (user_name!=NULL && strncmp(user_name, "guest", 5)==0)) permission = 3; else{ permission = get_permission( user_name, usbdisk_rel_sub_path, usbdisk_sub_share_folder, "cifs"); } Cdbg(DBE, "usbdisk_rel_sub_path=%s, usbdisk_sub_share_folder=%s, permission=%d, user_name=%s", usbdisk_rel_sub_path, usbdisk_sub_share_folder, permission, user_name); #endif return permission; }
int chunkqueue_append_smb_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) { chunk *c; if (len == 0) return 0; c = chunkqueue_get_unused_chunk(cq); c->type = SMB_CHUNK; buffer_copy_string_buffer(c->file.name, fn); c->file.start = offset; c->file.length = len; c->offset = 0; //- JerryLin add c->roffset = 0; c->open_thread = -1; c->listcount = 0; Cdbg(1,"chunkqueue_append_smb_file.....fn=[%s]", fn->ptr); chunkqueue_append_chunk(cq, c); return 0; }
int config_patch_connection(server *srv, connection *con, comp_key_t comp) { size_t i, j; con->conditional_is_valid[comp] = 1; /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; specific_config *s = srv->config_storage[i]; /* condition didn't match */ if (!config_check_cond(srv, con, dc)) continue; /* merge config */ for (j = 0; j < dc->value->used; j++) { data_unset *du = dc->value->data[j]; if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) { PATCH(document_root); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("smbdav.auth_ntlm"))) { PATCH(auth_ntlm_list); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) { PATCH(range_requests); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.error-handler-404"))) { PATCH(error_handler); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.errorfile-prefix"))) { PATCH(errorfile_prefix); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.assign"))) { PATCH(mimetypes); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-requests"))) { PATCH(max_keep_alive_requests); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-idle"))) { PATCH(max_keep_alive_idle); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-write-idle"))) { PATCH(max_write_idle); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-read-idle"))) { PATCH(max_read_idle); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.use-xattr"))) { PATCH(use_xattr); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-inode"))) { PATCH(etag_use_inode); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-mtime"))) { PATCH(etag_use_mtime); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) { PATCH(etag_use_size); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) { PATCH(ssl_pemfile); #ifdef USE_OPENSSL PATCH(ssl_ctx); #endif } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) { PATCH(ssl_ca_file); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) { PATCH(ssl_use_sslv2); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv3"))) { PATCH(ssl_use_sslv3); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) { PATCH(ssl_cipher_list); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) { PATCH(is_ssl); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.dh-file"))) { PATCH(ssl_dh_file); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ec-curve"))) { PATCH(ssl_ec_curve); #ifdef HAVE_LSTAT } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) { PATCH(follow_symlink); #endif } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.name"))) { buffer_copy_string_buffer(con->server_name, s->server_name); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.tag"))) { PATCH(server_tag); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("connection.kbytes-per-second"))) { PATCH(kbytes_per_second); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-handling"))) { PATCH(log_request_handling); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-header"))) { PATCH(log_request_header); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-response-header"))) { PATCH(log_response_header); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) { PATCH(log_condition_handling); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) { PATCH(log_file_not_found); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-ssl-noise"))) { PATCH(log_ssl_noise); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-timeouts"))) { PATCH(log_timeouts); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) { PATCH(allow_http11); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) { PATCH(force_lowercase_filenames); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) { PATCH(global_kbytes_per_second); PATCH(global_bytes_per_second_cnt); con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt; } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.activate"))) { PATCH(ssl_verifyclient); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.enforce"))) { PATCH(ssl_verifyclient_enforce); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.depth"))) { PATCH(ssl_verifyclient_depth); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) { PATCH(ssl_verifyclient_username); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) { PATCH(ssl_verifyclient_export_cert); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.arpping-interface"))) { Cdbg(DBE, "arpping_interface"); //PATCH(arpping_interface); } } } con->etag_flags = (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) | (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) | (con->conf.etag_use_size ? ETAG_USE_SIZE : 0); return 0; }
void read_sharelink_list(){ #if EMBEDDED_EANBLE char* aa = nvram_get_sharelink_str(); if(aa==NULL){ return; } char* str_sharelink_list = (char*)malloc(strlen(aa)+1); strcpy(str_sharelink_list, aa); if(str_sharelink_list!=NULL){ char * pch; pch = strtok(str_sharelink_list, "<>"); while(pch!=NULL){ int b_addto_list = 1; share_link_info_t *smb_sharelink_info; smb_sharelink_info = (share_link_info_t *)calloc(1, sizeof(share_link_info_t)); smb_sharelink_info->toshare = 1; //- Share Path if(pch){ Cdbg(DBE, "share path=%s", pch); smb_sharelink_info->shortpath = buffer_init(); buffer_copy_string_len(smb_sharelink_info->shortpath, pch, strlen(pch)); } //- Real Path pch = strtok(NULL,"<>"); if(pch){ Cdbg(DBE, "real path=%s", pch); smb_sharelink_info->realpath = buffer_init(); buffer_copy_string_len(smb_sharelink_info->realpath, pch, strlen(pch)); } //- File Name pch = strtok(NULL,"<>"); if(pch){ Cdbg(DBE, "file name=%s", pch); smb_sharelink_info->filename = buffer_init(); buffer_copy_string_len(smb_sharelink_info->filename, pch, strlen(pch)); } //- Auth pch = strtok(NULL,"<>"); if(pch){ Cdbg(DBE, "auth=%s", pch); smb_sharelink_info->auth = buffer_init(); buffer_copy_string_len(smb_sharelink_info->auth, pch, strlen(pch)); } //- Expire Time pch = strtok(NULL,"<>"); if(pch){ smb_sharelink_info->expiretime = atoi(pch); time_t cur_time = time(NULL); double offset = difftime(smb_sharelink_info->expiretime, cur_time); if( smb_sharelink_info->expiretime !=0 && offset < 0.0 ){ free_share_link_info(smb_sharelink_info); free(smb_sharelink_info); b_addto_list = 0; } } //- Create Time pch = strtok(NULL,"<>"); if(pch){ smb_sharelink_info->createtime = atoi(pch); } if(b_addto_list==1) DLIST_ADD(share_link_info_list, smb_sharelink_info); //- Next pch = strtok(NULL,"<>"); } } #else size_t j; int length, filesize; FILE* fp = fopen(g_temp_sharelink_file, "r"); if(fp!=NULL){ char str[1024]; while(fgets(str,sizeof(str),fp) != NULL) { char * pch; int b_addto_list = 1; // strip trailing '\n' if it exists int len = strlen(str)-1; if(str[len] == '\n') str[len] = 0; share_link_info_t *smb_sharelink_info; smb_sharelink_info = (share_link_info_t *)calloc(1, sizeof(share_link_info_t)); smb_sharelink_info->toshare = 1; //- Share Path pch = strtok(str,"<"); if(pch){ smb_sharelink_info->shortpath = buffer_init(); buffer_copy_string_len(smb_sharelink_info->shortpath, pch, strlen(pch)); } //- Real Path pch = strtok(NULL,"<"); if(pch){ smb_sharelink_info->realpath = buffer_init(); buffer_copy_string_len(smb_sharelink_info->realpath, pch, strlen(pch)); } //- File Name pch = strtok(NULL,"<"); if(pch){ smb_sharelink_info->filename = buffer_init(); buffer_copy_string_len(smb_sharelink_info->filename, pch, strlen(pch)); } //- Auth pch = strtok(NULL,"<"); if(pch){ smb_sharelink_info->auth = buffer_init(); buffer_copy_string_len(smb_sharelink_info->auth, pch, strlen(pch)); } //- Expire Time pch = strtok(NULL,"<"); if(pch){ smb_sharelink_info->expiretime = atoi(pch); time_t cur_time = time(NULL); double offset = difftime(smb_sharelink_info->expiretime, cur_time); if( smb_sharelink_info->expiretime !=0 && offset < 0.0 ){ free_share_link_info(smb_sharelink_info); free(smb_sharelink_info); b_addto_list = 0; } } //- Create Time pch = strtok(NULL,"<"); if(pch){ smb_sharelink_info->createtime = atoi(pch); } if(b_addto_list==1) DLIST_ADD(share_link_info_list, smb_sharelink_info); } fclose(fp); } #endif }
int smbc_parser_basic_authentication(server *srv, connection* con, char** username, char** password){ if (con->mode != SMB_BASIC&&con->mode != DIRECT) return 0; data_string* ds = (data_string *)array_get_element(con->request.headers, "Authorization"); if(con->share_link_basic_auth->used){ Cdbg(1, "Use for Sharelink, con->share_link_basic_auth=[%s]", con->share_link_basic_auth->ptr); ds = data_string_init(); buffer_copy_string_buffer( ds->value, con->share_link_basic_auth ); buffer_reset(con->share_link_basic_auth); con->is_share_link = 1; } else con->is_share_link = 0; if (ds != NULL) { char *http_authorization = NULL; http_authorization = ds->value->ptr; if(strncmp(http_authorization, "Basic ", 6) == 0) { buffer *basic_msg = buffer_init(); buffer *user = buffer_init(); buffer *pass = buffer_init(); if (!base64_decode(basic_msg, &http_authorization[6])) { log_error_write(srv, __FILE__, __LINE__, "sb", "decodeing base64-string failed", basic_msg); buffer_free(basic_msg); free(user); free(pass); return 0; } char *s, bmsg[1024] = {0}; //fetech the username and password from credential memcpy(bmsg, basic_msg->ptr, basic_msg->used); s = strchr(bmsg, ':'); bmsg[s-bmsg] = '\0'; buffer_copy_string(user, bmsg); buffer_copy_string(pass, s+1); *username = (char*)malloc(user->used); strcpy(*username, user->ptr); *password = (char*)malloc(pass->used); strcpy(*password, pass->ptr); buffer_free(basic_msg); free(user); free(pass); Cdbg(DBE, "base64_decode=[%s][%s]", *username, *password); return 1; } } else Cdbg(DBE, "smbc_parser_basic_authentication: ds == NULL"); return 0; }
handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **ret_sce) { #ifdef HAVE_FAM_H fam_dir_entry *fam_dir = NULL; int dir_ndx = -1; splay_tree *dir_node = NULL; #endif stat_cache_entry *sce = NULL; stat_cache *sc; struct stat st; size_t k; int fd; struct stat lst; #ifdef DEBUG_STAT_CACHE size_t i; #endif int file_ndx; splay_tree *file_node = NULL; *ret_sce = NULL; /* * check if the directory for this file has changed */ sc = srv->stat_cache; buffer_copy_string_buffer(sc->hash_key, name); buffer_append_long(sc->hash_key, con->conf.follow_symlink); file_ndx = hashme(sc->hash_key); sc->files = splaytree_splay(sc->files, file_ndx); #ifdef DEBUG_STAT_CACHE for (i = 0; i < ctrl.used; i++) { if (ctrl.ptr[i] == file_ndx) break; } #endif if (sc->files && (sc->files->key == file_ndx)) { #ifdef DEBUG_STAT_CACHE /* it was in the cache */ assert(i < ctrl.used); #endif /* we have seen this file already and * don't stat() it again in the same second */ file_node = sc->files; sce = file_node->data; /* check if the name is the same, we might have a collision */ if (buffer_is_equal(name, sce->name)) { if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) { if (sce->stat_ts == srv->cur_ts) { *ret_sce = sce; return HANDLER_GO_ON; } } } else { /* oops, a collision, * * file_node is used by the FAM check below to see if we know this file * and if we can save a stat(). * * BUT, the sce is not reset here as the entry into the cache is ok, we * it is just not pointing to our requested file. * * */ file_node = NULL; } } else { #ifdef DEBUG_STAT_CACHE if (i != ctrl.used) { log_error_write(srv, __FILE__, __LINE__, "xSB", file_ndx, "was already inserted but not found in cache, ", name); } assert(i == ctrl.used); #endif } #ifdef HAVE_FAM_H /* dir-check */ if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) { if (0 != buffer_copy_dirname(sc->dir_name, name)) { log_error_write(srv, __FILE__, __LINE__, "sb", "no '/' found in filename:", name); return HANDLER_ERROR; } buffer_copy_string_buffer(sc->hash_key, sc->dir_name); buffer_append_long(sc->hash_key, con->conf.follow_symlink); dir_ndx = hashme(sc->hash_key); sc->dirs = splaytree_splay(sc->dirs, dir_ndx); if (sc->dirs && (sc->dirs->key == dir_ndx)) { dir_node = sc->dirs; } if (dir_node && file_node) { /* we found a file */ sce = file_node->data; fam_dir = dir_node->data; if (fam_dir->version == sce->dir_version) { /* the stat()-cache entry is still ok */ *ret_sce = sce; return HANDLER_GO_ON; } } } #endif /* * *lol* * - open() + fstat() on a named-pipe results in a (intended) hang. * - stat() if regular file + open() to see if we can read from it is better * * */ int r; #ifdef HAVE_LIBSMBCLIENT if(con->mode == DIRECT) r = stat(name->ptr, &st); else if(con->mode == SMB_NTLM||con->mode == SMB_BASIC) r = smbc_wrapper_stat(con, name->ptr, &st); #else r = stat(name->ptr, &st); #endif if (r == -1) { return HANDLER_ERROR; } if (S_ISREG(st.st_mode)) { /* fix broken stat/open for symlinks to reg files with appended slash on freebsd,osx */ if (name->ptr[name->used-2] == '/') { errno = ENOTDIR; return HANDLER_ERROR; } /* try to open the file to check if we can read it */ #ifdef HAVE_LIBSMBCLIENT if(con->mode == DIRECT) { fd = open(name->ptr, O_RDONLY); if(fd == -1) { return HANDLER_ERROR; } close(fd); } else if(con->mode == SMB_NTLM) { smb_file_t *fp; fp = smbc_cli_ntcreate(con->smb_info->cli, name->ptr, FILE_READ_DATA | FILE_WRITE_DATA, FILE_OPEN, 0); if(fp == NULL) { return HANDLER_ERROR; } smbc_cli_close(con->smb_info->cli, fp); } else { //Cdbg(DBE, "call smbc_open..%s", con->smb_info->url.path->ptr); //Cdbg(DBE, "call smbc_open..%s", name->ptr); //fd = smbc_open(con->smb_info->url.path->ptr, O_RDONLY, 0); fd = smbc_open(name->ptr, O_RDONLY, 0); if(fd == -1) { Cdbg(DBE, "fail to smbc_open"); return HANDLER_ERROR; } //Cdbg(DBE, "call smbc_close"); smbc_close(fd); } #else if (-1 == (fd = open(name->ptr, O_RDONLY))) { return HANDLER_ERROR; } close(fd); #endif } if (NULL == sce) { #ifdef DEBUG_STAT_CACHE int osize = splaytree_size(sc->files); #endif sce = stat_cache_entry_init(); buffer_copy_string_buffer(sce->name, name); sc->files = splaytree_insert(sc->files, file_ndx, sce); #ifdef DEBUG_STAT_CACHE if (ctrl.size == 0) { ctrl.size = 16; ctrl.used = 0; ctrl.ptr = malloc(ctrl.size * sizeof(*ctrl.ptr)); } else if (ctrl.size == ctrl.used) { ctrl.size += 16; ctrl.ptr = realloc(ctrl.ptr, ctrl.size * sizeof(*ctrl.ptr)); } ctrl.ptr[ctrl.used++] = file_ndx; assert(sc->files); assert(sc->files->data == sce); assert(osize + 1 == splaytree_size(sc->files)); #endif } sce->st = st; sce->stat_ts = srv->cur_ts; /* catch the obvious symlinks * * this is not a secure check as we still have a race-condition between * the stat() and the open. We can only solve this by * 1. open() the file * 2. fstat() the fd * * and keeping the file open for the rest of the time. But this can * only be done at network level. * * per default it is not a symlink * */ #ifdef HAVE_LSTAT sce->is_symlink = 0; /* we want to only check for symlinks if we should block symlinks. */ if (!con->conf.follow_symlink) { if (stat_cache_lstat(srv, name, &lst) == 0) { #ifdef DEBUG_STAT_CACHE log_error_write(srv, __FILE__, __LINE__, "sb", "found symlink", name); #endif sce->is_symlink = 1; } /* * we assume "/" can not be symlink, so * skip the symlink stuff if our path is / **/ else if ((name->used > 2)) { buffer *dname; char *s_cur; dname = buffer_init(); buffer_copy_string_buffer(dname, name); while ((s_cur = strrchr(dname->ptr,'/'))) { *s_cur = '\0'; dname->used = s_cur - dname->ptr + 1; if (dname->ptr == s_cur) { #ifdef DEBUG_STAT_CACHE log_error_write(srv, __FILE__, __LINE__, "s", "reached /"); #endif break; } #ifdef DEBUG_STAT_CACHE log_error_write(srv, __FILE__, __LINE__, "sbs", "checking if", dname, "is a symlink"); #endif if (stat_cache_lstat(srv, dname, &lst) == 0) { sce->is_symlink = 1; #ifdef DEBUG_STAT_CACHE log_error_write(srv, __FILE__, __LINE__, "sb", "found symlink", dname); #endif break; }; }; buffer_free(dname); }; }; #endif if (S_ISREG(st.st_mode)) { /* determine mimetype */ buffer_reset(sce->content_type); #ifdef HAVE_XATTR if (con->conf.use_xattr) { stat_cache_attr_get(sce->content_type, name->ptr); } #endif /* xattr did not set a content-type. ask the config */ if (buffer_is_empty(sce->content_type)) { for (k = 0; k < con->conf.mimetypes->used; k++) { data_string *ds = (data_string *)con->conf.mimetypes->data[k]; buffer *type = ds->key; if (type->used == 0) continue; /* check if the right side is the same */ if (type->used > name->used) continue; if (0 == strncasecmp(name->ptr + name->used - type->used, type->ptr, type->used - 1)) { buffer_copy_string_buffer(sce->content_type, ds->value); break; } } } etag_create(sce->etag, &(sce->st), con->etag_flags); } else if (S_ISDIR(st.st_mode)) { etag_create(sce->etag, &(sce->st), con->etag_flags); } #ifdef HAVE_FAM_H if (sc->fam && (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) { /* is this directory already registered ? */ if (!dir_node) { fam_dir = fam_dir_entry_init(); fam_dir->fc = sc->fam; buffer_copy_string_buffer(fam_dir->name, sc->dir_name); fam_dir->version = 1; fam_dir->req = calloc(1, sizeof(FAMRequest)); if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr, fam_dir->req, fam_dir)) { log_error_write(srv, __FILE__, __LINE__, "sbsbs", "monitoring dir failed:", fam_dir->name, "file:", name, FamErrlist[FAMErrno]); fam_dir_entry_free(fam_dir); } else { int osize = 0; if (sc->dirs) { osize = sc->dirs->size; } sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir); assert(sc->dirs); assert(sc->dirs->data == fam_dir); assert(osize == (sc->dirs->size - 1)); } } else { fam_dir = dir_node->data; } /* bind the fam_fc to the stat() cache entry */ if (fam_dir) { sce->dir_version = fam_dir->version; sce->dir_ndx = dir_ndx; } } #endif *ret_sce = sce; return HANDLER_GO_ON; }
int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) { chunk *c; size_t chunks_written = 0; fprintf(stderr,"network_write_chunkqueue_write"); for(c = cq->first; c; c = c->next) { int chunk_finished = 0; switch(c->type) { case MEM_CHUNK: { char * offset; size_t toSend; ssize_t r; if (c->mem->used == 0) { chunk_finished = 1; break; } offset = c->mem->ptr + c->offset; toSend = c->mem->used - 1 - c->offset; #ifdef __WIN32 if ((r = send(fd, offset, toSend, 0)) < 0) { /* no error handling for windows... */ log_error_write(srv, __FILE__, __LINE__, "ssd", "send failed: ", strerror(errno), fd); return -1; } #else if ((r = write(fd, offset, toSend)) < 0) { switch (errno) { case EAGAIN: case EINTR: r = 0; break; case EPIPE: case ECONNRESET: return -2; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), fd); return -1; } } #endif c->offset += r; cq->bytes_out += r; if (c->offset == (off_t)c->mem->used - 1) { chunk_finished = 1; } break; } case FILE_CHUNK: { #ifdef USE_MMAP char *p = NULL; #endif ssize_t r; off_t offset; size_t toSend; stat_cache_entry *sce = NULL; int ifd; if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), c->file.name); return -1; } offset = c->file.start + c->offset; toSend = c->file.length - c->offset; if (offset > sce->st.st_size) { log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name); return -1; } if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); return -1; } #ifdef USE_MMAP if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno)); close(ifd); return -1; } close(ifd); if ((r = write(fd, p + offset, toSend)) <= 0) { switch (errno) { case EAGAIN: case EINTR: r = 0; break; case EPIPE: case ECONNRESET: munmap(p, sce->st.st_size); return -2; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), fd); munmap(p, sce->st.st_size); return -1; } } munmap(p, sce->st.st_size); #else /* USE_MMAP */ buffer_prepare_copy(srv->tmp_buf, toSend); lseek(ifd, offset, SEEK_SET); if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) { log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno)); close(ifd); return -1; } close(ifd); #ifdef __WIN32 if ((r = send(fd, srv->tmp_buf->ptr, toSend, 0)) < 0) { /* no error handling for windows... */ log_error_write(srv, __FILE__, __LINE__, "ssd", "send failed: ", strerror(errno), fd); return -1; } #else /* __WIN32 */ if ((r = write(fd, srv->tmp_buf->ptr, toSend)) < 0) { switch (errno) { case EAGAIN: case EINTR: r = 0; break; case EPIPE: case ECONNRESET: return -2; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), fd); return -1; } } #endif /* __WIN32 */ #endif /* USE_MMAP */ c->offset += r; cq->bytes_out += r; if (c->offset == c->file.length) { chunk_finished = 1; } break; } case SMB_CHUNK: { ssize_t r; off_t offset; size_t toSend; off_t rest_len; stat_cache_entry *sce = NULL; //#define BUFF_SIZE 2048 #define BUFF_SIZE 100*1024 char buff[BUFF_SIZE]; // char *buff=NULL; int ifd; if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), c->file.name); Cdbg(DBE,"stat cache get entry failed"); return -1; } offset = c->file.start + c->offset; toSend = (c->file.length - c->offset>BUFF_SIZE)? BUFF_SIZE : c->file.length - c->offset ; // rest_len = c->file.length - c->offset; // toSend = Cdbg(DBE,"offset =%lli, toSend=%d, sce->st.st_size=%lli", offset, toSend, sce->st.st_size); if (offset > sce->st.st_size) { log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name); Cdbg(DBE,"offset > size"); if(buff) free(buff); return -1; } // if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { if (-1 == (ifd = smbc_wrapper_open(con,c->file.name->ptr, O_RDONLY, 0755))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); Cdbg(DBE,"wrapper open failed,ifd=%d, fn =%s, open failed =%s, errno =%d",ifd, c->file.name->ptr,strerror(errno),errno); return -1; } Cdbg(DBE,"ifd =%d, toSend=%d",ifd, toSend); smbc_wrapper_lseek(con, ifd, offset, SEEK_SET ); if (-1 == (toSend = smbc_wrapper_read(con, ifd, buff, toSend ))) { log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno)); smbc_wrapper_close(con, ifd); Cdbg(DBE,"ifd =%d,toSend =%d, errno=%s",ifd,toSend, strerror(errno)); return -1; } Cdbg(DBE,"close ifd=%d, toSend=%d",ifd,toSend); smbc_wrapper_close(con, ifd); Cdbg(DBE,"write socket fd=%d",fd); if ((r = write(fd, buff, toSend)) < 0) { switch (errno) { case EAGAIN: case EINTR: r = 0; break; case EPIPE: case ECONNRESET: return -2; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), fd); return -1; } } c->offset += r; cq->bytes_out += r; Cdbg(DBE,"r =%d",r); if (c->offset == c->file.length) { chunk_finished = 1; } break; } default: log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known"); return -1; } if (!chunk_finished) { /* not finished yet */ break; } chunks_written++; } return chunks_written; }
int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) { chunk *c; size_t chunks_written = 0; for(c = cq->first; c; c = c->next) { int chunk_finished = 0; switch(c->type) { case MEM_CHUNK: { char * offset; size_t toSend; ssize_t r; size_t num_chunks, i; struct iovec *chunks; chunk *tc; size_t num_bytes = 0; #if defined(_SC_IOV_MAX) /* IRIX, MacOS X, FreeBSD, Solaris, ... */ const size_t max_chunks = sysconf(_SC_IOV_MAX); #elif defined(IOV_MAX) /* Linux x86 (glibc-2.3.6-3) */ const size_t max_chunks = IOV_MAX; #elif defined(MAX_IOVEC) /* Linux ia64 (glibc-2.3.3-98.28) */ const size_t max_chunks = MAX_IOVEC; #elif defined(UIO_MAXIOV) /* Linux x86 (glibc-2.2.5-233) */ const size_t max_chunks = UIO_MAXIOV; #elif (defined(__FreeBSD__) && __FreeBSD_version < 500000) || defined(__DragonFly__) || defined(__APPLE__) /* - FreeBSD 4.x * - MacOS X 10.3.x * (covered in -DKERNEL) * */ const size_t max_chunks = 1024; /* UIO_MAXIOV value from sys/uio.h */ #else #error "sysconf() doesnt return _SC_IOV_MAX ..., check the output of 'man writev' for the EINVAL error and send the output to [email protected]" #endif /* we can't send more then SSIZE_MAX bytes in one chunk */ /* build writev list * * 1. limit: num_chunks < max_chunks * 2. limit: num_bytes < SSIZE_MAX */ for (num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < max_chunks; num_chunks++, tc = tc->next); chunks = calloc(num_chunks, sizeof(*chunks)); for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) { if (tc->mem->used == 0) { chunks[i].iov_base = tc->mem->ptr; chunks[i].iov_len = 0; } else { offset = tc->mem->ptr + tc->offset; toSend = tc->mem->used - 1 - tc->offset; chunks[i].iov_base = offset; /* protect the return value of writev() */ if (toSend > SSIZE_MAX || num_bytes + toSend > SSIZE_MAX) { chunks[i].iov_len = SSIZE_MAX - num_bytes; num_chunks = i + 1; break; } else { chunks[i].iov_len = toSend; } num_bytes += toSend; } } if ((r = writev(fd, chunks, num_chunks)) < 0) { switch (errno) { case EAGAIN: case EINTR: r = 0; break; case EPIPE: case ECONNRESET: free(chunks); return -2; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "writev failed:", strerror(errno), fd); free(chunks); return -1; } } cq->bytes_out += r; /* check which chunks have been written */ for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) { if (r >= (ssize_t)chunks[i].iov_len) { /* written */ r -= chunks[i].iov_len; tc->offset += chunks[i].iov_len; if (chunk_finished) { /* skip the chunks from further touches */ chunks_written++; c = c->next; } else { /* chunks_written + c = c->next is done in the for()*/ chunk_finished++; } } else { /* partially written */ tc->offset += r; chunk_finished = 0; break; } } free(chunks); break; } case FILE_CHUNK: { ssize_t r; off_t abs_offset; off_t toSend; stat_cache_entry *sce = NULL; #define KByte * 1024 #define MByte * 1024 KByte #define GByte * 1024 MByte const off_t we_want_to_mmap = 512 KByte; char *start = NULL; if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), c->file.name); return -1; } abs_offset = c->file.start + c->offset; if (abs_offset > sce->st.st_size) { log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name); return -1; } /* mmap the buffer * - first mmap * - new mmap as the we are at the end of the last one */ if (c->file.mmap.start == MAP_FAILED || abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) { /* Optimizations for the future: * * adaptive mem-mapping * the problem: * we mmap() the whole file. If someone has alot large files and 32bit * machine the virtual address area will be unrun and we will have a failing * mmap() call. * solution: * only mmap 16M in one chunk and move the window as soon as we have finished * the first 8M * * read-ahead buffering * the problem: * sending out several large files in parallel trashes the read-ahead of the * kernel leading to long wait-for-seek times. * solutions: (increasing complexity) * 1. use madvise * 2. use a internal read-ahead buffer in the chunk-structure * 3. use non-blocking IO for file-transfers * */ /* all mmap()ed areas are 512kb expect the last which might be smaller */ off_t we_want_to_send; size_t to_mmap; /* this is a remap, move the mmap-offset */ if (c->file.mmap.start != MAP_FAILED) { munmap(c->file.mmap.start, c->file.mmap.length); c->file.mmap.offset += we_want_to_mmap; } else { /* in case the range-offset is after the first mmap()ed area we skip the area */ c->file.mmap.offset = 0; while (c->file.mmap.offset + we_want_to_mmap < c->file.start) { c->file.mmap.offset += we_want_to_mmap; } } /* length is rel, c->offset too, assume there is no limit at the mmap-boundaries */ we_want_to_send = c->file.length - c->offset; to_mmap = (c->file.start + c->file.length) - c->file.mmap.offset; /* we have more to send than we can mmap() at once */ if (abs_offset + we_want_to_send > c->file.mmap.offset + we_want_to_mmap) { we_want_to_send = (c->file.mmap.offset + we_want_to_mmap) - abs_offset; to_mmap = we_want_to_mmap; } if (-1 == c->file.fd) { /* open the file if not already open */ if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno)); return -1; } #ifdef FD_CLOEXEC fcntl(c->file.fd, F_SETFD, FD_CLOEXEC); #endif } if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) { /* close it here, otherwise we'd have to set FD_CLOEXEC */ log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:", strerror(errno), c->file.name, c->file.fd); return -1; } c->file.mmap.length = to_mmap; #ifdef LOCAL_BUFFERING buffer_copy_string_len(c->mem, c->file.mmap.start, c->file.mmap.length); #else #ifdef HAVE_MADVISE /* don't advise files < 64Kb */ if (c->file.mmap.length > (64 KByte)) { /* darwin 7 is returning EINVAL all the time and I don't know how to * detect this at runtime.i * * ignore the return value for now */ madvise(c->file.mmap.start, c->file.mmap.length, MADV_WILLNEED); } #endif #endif /* chunk_reset() or chunk_free() will cleanup for us */ } /* to_send = abs_mmap_end - abs_offset */ toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset); if (toSend < 0) { log_error_write(srv, __FILE__, __LINE__, "soooo", "toSend is negative:", toSend, c->file.mmap.length, abs_offset, c->file.mmap.offset); assert(toSend < 0); } #ifdef LOCAL_BUFFERING start = c->mem->ptr; #else start = c->file.mmap.start; #endif if ((r = write(fd, start + (abs_offset - c->file.mmap.offset), toSend)) < 0) { switch (errno) { case EAGAIN: case EINTR: r = 0; break; case EPIPE: case ECONNRESET: return -2; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), fd); return -1; } } c->offset += r; cq->bytes_out += r; if (c->offset == c->file.length) { chunk_finished = 1; /* we don't need the mmaping anymore */ if (c->file.mmap.start != MAP_FAILED) { munmap(c->file.mmap.start, c->file.mmap.length); c->file.mmap.start = MAP_FAILED; } } break; } case SMB_CHUNK: { ssize_t r; off_t offset; size_t toSend; off_t rest_len; stat_cache_entry *sce = NULL; //#define BUFF_SIZE 2048 //- 256K #define BUFF_SIZE 256*1024 char buff[BUFF_SIZE]={0}; // memset(buff,0,BUFF_SIZE); // char *buff=NULL; int ifd; if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), c->file.name); Cdbg(DBE,"stat cache get entry failed"); return -1; } offset = c->file.start + c->offset; toSend = (c->file.length - c->offset>BUFF_SIZE)? BUFF_SIZE : c->file.length - c->offset ; // rest_len = c->file.length - c->offset; // toSend = Cdbg(DBE,"offset =%lli, toSend=%d, sce->st.st_size=%lli", offset, toSend, sce->st.st_size); if (offset > sce->st.st_size) { log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name); Cdbg(DBE,"offset > size"); return -1; } // if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { if (-1 == (ifd = smbc_wrapper_open(con,c->file.name->ptr, O_RDONLY, 0755))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); Cdbg(DBE,"wrapper open failed,ifd=%d, fn =%s, open failed =%s, errno =%d",ifd, c->file.name->ptr,strerror(errno),errno); return -1; } Cdbg(DBE,"ifd =%d, toSend=%d",ifd, toSend); smbc_wrapper_lseek(con, ifd, offset, SEEK_SET ); if (-1 == (toSend = smbc_wrapper_read(con, ifd, buff, toSend ))) { log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno)); smbc_wrapper_close(con, ifd); Cdbg(DBE,"ifd =%d,toSend =%d, errno=%s",ifd,toSend, strerror(errno)); return -1; } Cdbg(DBE,"close ifd=%d, toSend=%d",ifd,toSend); smbc_wrapper_close(con, ifd); Cdbg(DBE,"write socket fd=%d",fd); if ((r = write(fd, buff, toSend)) < 0) { switch (errno) { case EAGAIN: case EINTR: r = 0; break; case EPIPE: case ECONNRESET: return -2; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), fd); return -1; } } c->offset += r; cq->bytes_out += r; Cdbg(DBE,"r =%d",r); if (c->offset == c->file.length) { chunk_finished = 1; } break; } default: log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known"); return -1; } if (!chunk_finished) { /* not finished yet */ break; } chunks_written++; } return chunks_written; }
static int aicloud_connection_smb_info_init(server *srv, connection *con, plugin_data *p) { UNUSED(srv); char pWorkgroup[30]={0}; char pServer[64]={0}; char pShare[1280]={0}; char pPath[1280]={0}; smbc_wrapper_parse_path2(con, pWorkgroup, pServer, pShare, pPath); buffer* bworkgroup = buffer_init(); buffer* bserver = buffer_init(); buffer* bshare = buffer_init(); buffer* bpath = buffer_init(); URI_QUERY_TYPE qflag = SMB_FILE_QUERY; if(pWorkgroup[0] != '\0') buffer_copy_string(bworkgroup, pWorkgroup); if(pServer[0] != '\0') { int isHost = smbc_check_connectivity(con->physical_auth_url->ptr); if(isHost) { buffer_copy_string(bserver, pServer); } else{ buffer_free(bworkgroup); buffer_free(bserver); buffer_free(bshare); buffer_free(bpath); return 2; } } else { if(qflag == SMB_FILE_QUERY) { qflag = SMB_HOST_QUERY; } } if(pServer[0] != '\0' && pShare[0] != '\0') { buffer_copy_string(bshare, pShare); } else { if(qflag == SMB_FILE_QUERY) { qflag = SMB_SHARE_QUERY; } } if(pServer[0] != '\0' && pShare[0] != '\0' && pPath[0] != '\0') { buffer_copy_string(bpath, pPath); qflag = SMB_FILE_QUERY; } data_string *ds = (data_string *)array_get_element(con->request.headers, "user-Agent"); smb_info_t *smb_info; if( ds && ( strstr( ds->value->ptr, "Mozilla" ) || strstr( ds->value->ptr, "Opera" ) || con->mode == SMB_NTLM ) ){ //- From browser, like IE, Chrome, Firefox, Safari if(smb_info = smbdav_get_smb_info_from_pool(srv, con, p)){ Cdbg(DBE, "Get smb_info from pool smb_info->qflag=[%d], smb_info->user=[%s], smb_info->pass=[%s]", smb_info->qflag, smb_info->username->ptr, smb_info->password->ptr); } else{ smb_info = calloc(1, sizeof(smb_info_t)); smb_info->username = buffer_init(); smb_info->password = buffer_init(); smb_info->workgroup = buffer_init(); smb_info->server = buffer_init(); smb_info->share = buffer_init(); smb_info->path = buffer_init(); smb_info->user_agent = buffer_init(); smb_info->src_ip = buffer_init(); if(con->mode == SMB_NTLM){ smb_info->cli = smbc_cli_initialize(); if(!buffer_is_empty(bserver)){ smbc_cli_connect(smb_info->cli, bserver->ptr, SMB_PORT); } smb_info->ntlmssp_state = NULL; smb_info->state = NTLMSSP_INITIAL; } DLIST_ADD(p->smb_info_list, smb_info); } con->smb_info = smb_info; } else{ smb_info = calloc(1, sizeof(smb_info_t)); smb_info->username = buffer_init(); smb_info->password = buffer_init(); smb_info->workgroup = buffer_init(); smb_info->server = buffer_init(); smb_info->share = buffer_init(); smb_info->path = buffer_init(); smb_info->user_agent = buffer_init(); smb_info->src_ip = buffer_init(); con->smb_info = smb_info; } con->smb_info->auth_time = time(NULL); con->smb_info->auth_right = 0; if(ds) buffer_copy_string(con->smb_info->user_agent, ds->value->ptr); con->smb_info->qflag = qflag; buffer_copy_string_buffer(con->smb_info->workgroup, bworkgroup); buffer_copy_string_buffer(con->smb_info->server, bserver); buffer_copy_string_buffer(con->smb_info->share, bshare); buffer_copy_string_buffer(con->smb_info->path, bpath); buffer_copy_string_buffer(con->smb_info->src_ip, con->dst_addr_buf); Cdbg(DBE, "con->smb_info->workgroup=[%s]", con->smb_info->workgroup->ptr); Cdbg(DBE, "con->smb_info->server=[%s]", con->smb_info->server->ptr); Cdbg(DBE, "con->smb_info->share=[%s]", con->smb_info->share->ptr); Cdbg(DBE, "con->smb_info->path=[%s]", con->smb_info->path->ptr); Cdbg(DBE, "con->smb_info->user_agent=[%s]", con->smb_info->user_agent->ptr); Cdbg(DBE, "con->smb_info->src_ip=[%s]", con->smb_info->src_ip->ptr); Cdbg(DBE, "con->smb_info->qflag=[%d]", con->smb_info->qflag); buffer_free(bworkgroup); buffer_free(bserver); buffer_free(bshare); buffer_free(bpath); return 1; }
static smb_info_t *smbdav_get_smb_info_from_pool(server *srv, connection *con, plugin_data *p) { smb_info_t *c; if(p->smb_info_list==NULL||con->mode==DIRECT) return NULL; //- Get user-Agent data_string *ds = (data_string *)array_get_element(con->request.headers, "user-Agent"); if(ds==NULL){ return NULL; } char pWorkgroup[30]={0}; char pServer[64]={0}; char pShare[1280]={0}; char pPath[1280]={0}; smbc_wrapper_parse_path2(con, pWorkgroup, pServer, pShare, pPath); buffer* buffer_server = buffer_init(); if(pServer[0] != '\0') buffer_append_string(buffer_server,pServer); buffer* buffer_share = buffer_init(); if(pShare[0] != '\0') buffer_append_string(buffer_share,pShare); int count = 0; for (c = p->smb_info_list; c; c = c->next) { count++; if(!buffer_is_equal(c->server, buffer_server)) continue; //Cdbg(DBE, "c->share=[%s], buffer_share=[%s]", c->share->ptr, buffer_share->ptr); //if(con->mode==SMB_BASIC && !buffer_is_equal(c->share, buffer_share)) // continue; //Cdbg(DBE, "%d, c->src_ip=[%s], dst_addr_buf=[%s]", count, c->src_ip->ptr, con->dst_addr_buf->ptr); if(!buffer_is_equal(c->src_ip, con->dst_addr_buf)) continue; Cdbg(DBE, "%d, c->user_agent=[%s], user_agent=[%s]", count, c->user_agent->ptr, ds->value->ptr); if(!buffer_is_equal(c->user_agent, ds->value)){ continue; } //Cdbg(DBE, "return %d, c->server=[%s]", count, c->server->ptr); buffer_free(buffer_server); buffer_free(buffer_share); return c; } buffer_free(buffer_server); buffer_free(buffer_share); return NULL; }
handler_t basic_authentication_handler(server *srv, connection *con, plugin_data *p) { data_string *ds_auth = (data_string *)array_get_element(con->request.headers, "Authorization"); buffer *user = buffer_init(); buffer *pass = buffer_init(); buffer_copy_string(user, " "); buffer_copy_string(pass, " "); //Cdbg(DBE, "*********** con->request.uri..%s", con->request.uri->ptr); char *auth_username = NULL; char *auth_password = NULL; if( smbc_parser_basic_authentication(srv, con, &auth_username, &auth_password) != 1 ){ if(con->smb_info==NULL) goto error_401; //Cdbg(DBE, "1111111, %s, %s", con->smb_info->username->ptr, con->smb_info->password->ptr); if( con->smb_info->username->used && con->smb_info->password->used ){ buffer_copy_string_buffer(user, con->smb_info->username); buffer_copy_string_buffer(pass, con->smb_info->password); } Cdbg(DBE, "fail smbc_parser_basic_authentication-> %s, %s", user->ptr, pass->ptr); } else{ buffer_copy_string(user, auth_username); buffer_copy_string(pass, auth_password); free(auth_username); free(auth_password); } time_t cur_time = time(NULL); double result = difftime(cur_time, con->smb_info->auth_time); Cdbg(DBE, "difftime=[%1f]", result); if(con->smb_info->qflag == SMB_HOST_QUERY) { data_string *ds2 = (data_string *)array_get_element(con->request.headers, "user-Agent"); //- MUST login again more than 30 minutes if(result>1800){ goto error_401; } if( con->smb_info && buffer_is_equal_string(con->smb_info->username, "RELOGIN", 7) ){ buffer_reset(con->smb_info->username); buffer_reset(con->smb_info->password); goto error_401; } if(con->smb_info->username->used && con->smb_info->password->used){ buffer_copy_string_buffer(user, con->smb_info->username); buffer_copy_string_buffer(pass, con->smb_info->password); Cdbg(DBE, "SMB_HOST_QUERY-->copy from smb_info user=[%s], pass=[%s]", user->ptr, pass->ptr); } #if EMBEDDED_EANBLE if( strcmp(user->ptr, nvram_get_http_username())!=0 || strcmp(pass->ptr, nvram_get_http_passwd())!=0 ){ Cdbg(DBE, "smbc_host_account_authentication fail user=[%s], pass=[%s]", user->ptr, pass->ptr); goto error_401; } #else if( strcmp(user->ptr, "admin")!=0 || strcmp(pass->ptr, "admin")!=0 ){ Cdbg(DBE, "smbc_host_account_authentication fail user=[%s], pass=[%s]", user->ptr, pass->ptr); goto error_401; } #endif } else { //- check user / password struct stat st; if( con->smb_info && buffer_is_equal_string(con->smb_info->username, "RELOGIN", 7) ){ buffer_reset(con->smb_info->username); buffer_reset(con->smb_info->password); goto error_401; } int res = smbc_server_check_creds( con->smb_info->server->ptr, con->smb_info->share->ptr, con->smb_info->workgroup->ptr, user->ptr, pass->ptr ); //if( res == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED)) { if( res == 0xc00000bb ){ buffer_free(user); buffer_free(pass); con->http_status = 406; return HANDLER_FINISHED; } else if(res != 0) { //the username/password for smb_server is not correct if(con->smb_info->username->used && con->smb_info->password->used){ buffer_copy_string_buffer(user, con->smb_info->username); buffer_copy_string_buffer(pass, con->smb_info->password); Cdbg(DBE, "Try to login again, server=%s, share=%s, user=%s, pass=%s", con->smb_info->server->ptr, con->smb_info->share->ptr, user->ptr, pass->ptr); //- MUST login again more than 30 minutes if(result>1800){ buffer_copy_string(pass, ""); } //sprintf(strr, "smb://%s:%s@%s", user->ptr, pass->ptr, con->request.uri->ptr+1); int res = smbc_server_check_creds(con->smb_info->server->ptr, con->smb_info->share->ptr, con->smb_info->workgroup->ptr, user->ptr, pass->ptr); if(res != 0) goto error_401; } else goto error_401; } } con->smb_info->auth_time = time(NULL); if( !buffer_is_equal_string(user, "no", 2) && !buffer_is_equal_string(pass, "no", 2)){ buffer_copy_string_buffer(con->smb_info->username, user); buffer_copy_string_buffer(con->smb_info->password, pass); Cdbg(DBE, "save username=[%s], password=[%s], time=[%d] to con->smb_info", con->smb_info->username->ptr, con->smb_info->password->ptr, con->smb_info->auth_time); } buffer_free(user); buffer_free(pass); return HANDLER_UNSET; error_401: buffer_free(user); buffer_free(pass); if(con->smb_info) con->smb_info->auth_time = time(NULL); smbc_wrapper_response_401(srv, con); return HANDLER_FINISHED; }
handler_t http_response_prepare(server *srv, connection *con) { handler_t r; Cdbg(DBE, "enter http_response_prepare..mode=[%d], status=[%d][%s]", con->mode, con->http_status, connection_get_state(con->http_status)); /* looks like someone has already done a decision */ if ( (con->mode == DIRECT || con->mode == SMB_BASIC || con->mode == SMB_NTLM) && (con->http_status != 0 && con->http_status != 200)) { /* remove a packets in the queue */ if (con->file_finished == 0) { chunkqueue_reset(con->write_queue); } return HANDLER_FINISHED; } /* no decision yet, build conf->filename */ if ( (con->mode == DIRECT || con->mode == SMB_BASIC || con->mode == SMB_NTLM) && con->physical.path->used == 0) { char *qstr; /* we only come here when we have the parse the full request again * * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a * problem here as mod_setenv might get called multiple times * * fastcgi-auth might lead to a COMEBACK too * fastcgi again dead server too * * mod_compress might add headers twice too * * */ config_cond_cache_reset(srv, con); config_setup_connection(srv, con); /* Perhaps this could be removed at other places. */ if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "run condition"); } config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */ /** * prepare strings * * - uri.path_raw * - uri.path (secure) * - uri.query * */ /** * Name according to RFC 2396 * * - scheme * - authority * - path * - query * * (scheme)://(authority)(path)?(query)#fragment * * */ if (con->conf.is_ssl) { buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("https")); } else { buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("http")); } buffer_copy_string_buffer(con->uri.authority, con->request.http_host); buffer_to_lower(con->uri.authority); config_patch_connection(srv, con, COMP_HTTP_SCHEME); /* Scheme: */ config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */ config_patch_connection(srv, con, COMP_HTTP_REMOTE_IP); /* Client-IP */ config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */ config_patch_connection(srv, con, COMP_HTTP_USER_AGENT);/* User-Agent: */ config_patch_connection(srv, con, COMP_HTTP_LANGUAGE); /* Accept-Language: */ config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */ config_patch_connection(srv, con, COMP_HTTP_REQUEST_METHOD); /* REQUEST_METHOD */ /** their might be a fragment which has to be cut away */ if (NULL != (qstr = strchr(con->request.uri->ptr, '#'))) { con->request.uri->used = qstr - con->request.uri->ptr; con->request.uri->ptr[con->request.uri->used++] = '\0'; } /** extract query string from request.uri */ if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) { buffer_copy_string(con->uri.query, qstr + 1); buffer_copy_string_len(con->uri.path_raw, con->request.uri->ptr, qstr - con->request.uri->ptr); } else { buffer_reset(con->uri.query); buffer_copy_string_buffer(con->uri.path_raw, con->request.uri); } if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- splitting Request-URI"); log_error_write(srv, __FILE__, __LINE__, "sb", "Request-URI : ", con->request.uri); log_error_write(srv, __FILE__, __LINE__, "sb", "URI-scheme : ", con->uri.scheme); log_error_write(srv, __FILE__, __LINE__, "sb", "URI-authority: ", con->uri.authority); log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path_raw); log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query); } /** * * call plugins * * - based on the raw URL * */ switch(r = plugins_call_handle_uri_raw(srv, con)) { case HANDLER_GO_ON: break; case HANDLER_FINISHED: case HANDLER_COMEBACK: case HANDLER_WAIT_FOR_EVENT: case HANDLER_ERROR: return r; default: log_error_write(srv, __FILE__, __LINE__, "sd", "handle_uri_raw: unknown return value", r); break; } /* build filename * * - decode url-encodings (e.g. %20 -> ' ') * - remove path-modifiers (e.g. /../) */ if (con->request.http_method == HTTP_METHOD_OPTIONS && con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') { /* OPTIONS * ... */ buffer_copy_string_buffer(con->uri.path, con->uri.path_raw); } else { buffer_copy_string_buffer(srv->tmp_buf, con->uri.path_raw); buffer_urldecode_path(srv->tmp_buf); buffer_path_simplify(con->uri.path, srv->tmp_buf); } if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- sanatising URI"); log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path); } #ifdef USE_OPENSSL if (con->conf.is_ssl && con->conf.ssl_verifyclient) { https_add_ssl_entries(con); } #endif /** * * call plugins * * - based on the clean URL * */ config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */ config_patch_connection(srv, con, COMP_HTTP_QUERY_STRING); /* HTTPqs */ /* do we have to downgrade to 1.0 ? */ if (!con->conf.allow_http11) { con->request.http_version = HTTP_VERSION_1_0; } switch(r = plugins_call_handle_uri_clean(srv, con)) { case HANDLER_GO_ON: break; case HANDLER_FINISHED: case HANDLER_COMEBACK: case HANDLER_WAIT_FOR_EVENT: case HANDLER_ERROR: return r; default: log_error_write(srv, __FILE__, __LINE__, ""); break; } if (con->request.http_method == HTTP_METHOD_OPTIONS && con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') { /* option requests are handled directly without checking of the path */ response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST")); con->http_status = 200; con->file_finished = 1; return HANDLER_FINISHED; } /*** * * border * * logical filename (URI) becomes a physical filename here * * * */ /* 1. stat() * ... ISREG() -> ok, go on * ... ISDIR() -> index-file -> redirect * * 2. pathinfo() * ... ISREG() * * 3. -> 404 * */ /* * SEARCH DOCUMENT ROOT */ /* set a default */ buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root); buffer_copy_string_buffer(con->physical.rel_path, con->uri.path); #if defined(__WIN32) || defined(__CYGWIN__) /* strip dots from the end and spaces * * windows/dos handle those filenames as the same file * * foo == foo. == foo..... == "foo... " == "foo.. ./" * * This will affect in some cases PATHINFO * * on native windows we could prepend the filename with \\?\ to circumvent * this behaviour. I have no idea how to push this through cygwin * * */ if (con->physical.rel_path->used > 1) { buffer *b = con->physical.rel_path; size_t i; if (b->used > 2 && b->ptr[b->used-2] == '/' && (b->ptr[b->used-3] == ' ' || b->ptr[b->used-3] == '.')) { b->ptr[b->used--] = '\0'; } for (i = b->used - 2; b->used > 1; i--) { if (b->ptr[i] == ' ' || b->ptr[i] == '.') { b->ptr[b->used--] = '\0'; } else { break; } } } #endif if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- before doc_root"); log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root); log_error_write(srv, __FILE__, __LINE__, "sb", "Rel-Path :", con->physical.rel_path); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } /* the docroot plugin should set the doc_root and might also set the physical.path * for us (all vhost-plugins are supposed to set the doc_root) * */ switch(r = plugins_call_handle_docroot(srv, con)) { case HANDLER_GO_ON: break; case HANDLER_FINISHED: case HANDLER_COMEBACK: case HANDLER_WAIT_FOR_EVENT: case HANDLER_ERROR: return r; default: log_error_write(srv, __FILE__, __LINE__, ""); break; } /* MacOS X and Windows can't distiguish between upper and lower-case * * convert to lower-case */ if (con->conf.force_lowercase_filenames) { buffer_to_lower(con->physical.rel_path); } /* the docroot plugins might set the servername, if they don't we take http-host */ if (buffer_is_empty(con->server_name)) { buffer_copy_string_buffer(con->server_name, con->uri.authority); } /** * create physical filename * -> physical.path = docroot + rel_path * */ buffer_copy_string_buffer(con->physical.path, con->physical.doc_root); BUFFER_APPEND_SLASH(con->physical.path); buffer_copy_string_buffer(con->physical.basedir, con->physical.path); if (con->physical.rel_path->used && con->physical.rel_path->ptr[0] == '/') { buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2); //buffer_append_string_encoded(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2, ENCODING_REL_URI); //Cdbg(1,"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa %s", con->physical.path->ptr); } else { buffer_append_string_buffer(con->physical.path, con->physical.rel_path); } if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root"); log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root); log_error_write(srv, __FILE__, __LINE__, "sb", "Rel-Path :", con->physical.rel_path); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } switch(r = plugins_call_handle_physical(srv, con)) { case HANDLER_GO_ON: break; case HANDLER_FINISHED: case HANDLER_COMEBACK: case HANDLER_WAIT_FOR_EVENT: case HANDLER_ERROR: return r; default: log_error_write(srv, __FILE__, __LINE__, ""); break; } if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical"); log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root); log_error_write(srv, __FILE__, __LINE__, "sb", "Rel-Path :", con->physical.rel_path); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } } /* * Noone catched away the file from normal path of execution yet (like mod_access) * * Go on and check of the file exists at all */ if (con->mode == DIRECT || con->mode == SMB_BASIC || con->mode == SMB_NTLM) { char *slash = NULL; char *pathinfo = NULL; int found = 0; stat_cache_entry *sce = NULL; if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } if ( HANDLER_ERROR != stat_cache_get_entry(srv, con, smbc_wrapper_physical_url_path(srv, con), &sce)) { /* file exists */ if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- file found"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } #ifdef HAVE_LSTAT if ((sce->is_symlink != 0) && !con->conf.follow_symlink) { con->http_status = 403; if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } buffer_reset(con->physical.path); return HANDLER_FINISHED; }; #endif if (S_ISDIR(sce->st.st_mode)) { if (con->uri.path->ptr[con->uri.path->used - 2] != '/') { /* redirect to .../ */ http_response_redirect_to_directory(srv, con); return HANDLER_FINISHED; } #ifdef HAVE_LSTAT } else if (!S_ISREG(sce->st.st_mode) && !sce->is_symlink) { #else } else if (!S_ISREG(sce->st.st_mode)) { #endif /* any special handling of non-reg files ?*/ } } else { switch (errno) { case EACCES: con->http_status = 403; if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } buffer_reset(con->physical.path); return HANDLER_FINISHED; case ENOENT: con->http_status = 404; if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- file not found"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } buffer_reset(con->physical.path); return HANDLER_FINISHED; case ENOTDIR: /* PATH_INFO ! :) */ break; default: /* we have no idea what happend. let's tell the user so. */ con->http_status = 500; buffer_reset(con->physical.path); log_error_write(srv, __FILE__, __LINE__, "ssbsb", "file not found ... or so: ", strerror(errno), con->uri.path, "->", con->physical.path); return HANDLER_FINISHED; } /* not found, perhaps PATHINFO */ buffer_copy_string_buffer(srv->tmp_buf, con->physical.path); do { if (slash) { buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr); } else { buffer_copy_string_buffer(con->physical.path, srv->tmp_buf); } if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) { found = S_ISREG(sce->st.st_mode); break; } if (pathinfo != NULL) { *pathinfo = '\0'; } slash = strrchr(srv->tmp_buf->ptr, '/'); if (pathinfo != NULL) { /* restore '/' */ *pathinfo = '/'; } if (slash) pathinfo = slash; } while ((found == 0) && (slash != NULL) && ((size_t)(slash - srv->tmp_buf->ptr) > (con->physical.basedir->used - 2))); if (found == 0) { /* no it really doesn't exists */ con->http_status = 404; if (con->conf.log_file_not_found) { log_error_write(srv, __FILE__, __LINE__, "sbsb", "file not found:", con->uri.path, "->", con->physical.path); } buffer_reset(con->physical.path); return HANDLER_FINISHED; } #ifdef HAVE_LSTAT if ((sce->is_symlink != 0) && !con->conf.follow_symlink) { con->http_status = 403; if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } buffer_reset(con->physical.path); return HANDLER_FINISHED; }; #endif /* we have a PATHINFO */ if (pathinfo) { buffer_copy_string(con->request.pathinfo, pathinfo); /* * shorten uri.path */ con->uri.path->used -= strlen(pathinfo); con->uri.path->ptr[con->uri.path->used - 1] = '\0'; } if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path); log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo); } } if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } /* call the handlers */ switch(r = plugins_call_handle_subrequest_start(srv, con)) { case HANDLER_GO_ON: /* request was not handled */ break; case HANDLER_FINISHED: default: if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished"); } /* something strange happend */ return r; } /* if we are still here, no one wanted the file, status 403 is ok I think */ if ((con->mode == DIRECT || con->mode == SMB_BASIC || con->mode == SMB_NTLM) && con->http_status == 0) { switch (con->request.http_method) { case HTTP_METHOD_OPTIONS: con->http_status = 200; break; default: con->http_status = 403; } return HANDLER_FINISHED; } } switch(r = plugins_call_handle_subrequest(srv, con)) { case HANDLER_GO_ON: /* request was not handled, looks like we are done */ return HANDLER_FINISHED; case HANDLER_FINISHED: /* request is finished */ default: /* something strange happend */ return r; } /* can't happen */ return HANDLER_COMEBACK; }
int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { int ret = -1; off_t written = 0; #ifdef TCP_CORK int corked = 0; #endif server_socket *srv_socket = con->srv_socket; if (con->conf.global_kbytes_per_second && *(con->conf.global_bytes_per_second_cnt_ptr) > con->conf.global_kbytes_per_second * 1024) { /* we reached the global traffic limit */ con->traffic_limit_reached = 1; joblist_append(srv, con); return 1; } written = cq->bytes_out; #ifdef TCP_CORK /* Linux: put a cork into the socket as we want to combine the write() calls * but only if we really have multiple chunks */ if (cq->first && cq->first->next) { corked = 1; setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); } #endif if (srv_socket->is_ssl) { #ifdef USE_OPENSSL ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq); #endif } else { ret = srv->network_backend_write(srv, con, con->fd, cq); } if (ret >= 0) { chunkqueue_remove_finished_chunks(cq); ret = chunkqueue_is_empty(cq) ? 0 : 1; } #ifdef TCP_CORK if (corked) { corked = 0; setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); } #endif written = cq->bytes_out - written; con->bytes_written += written; con->bytes_written_cur_second += written; *(con->conf.global_bytes_per_second_cnt_ptr) += written; if (con->conf.kbytes_per_second && (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) { /* we reached the traffic limit */ con->traffic_limit_reached = 1; joblist_append(srv, con); } Cdbg(DBE, "leave with ret=[%d]", ret); return ret; }