/* should return an index or handle to list of included files */ int findFileInDir(char *dir, char *name) { char * buf, *p1, *p2, *peon; char *suffix=option_isuffix; unsigned int buflen; debugParserpp("include findFileInDir: dir %s, name %s, suffix %s\n",dir,name,suffix); buflen=strlen(dir)+strlen(name)+5; if(suffix!=NULL) buflen+=strlen(suffix); buf=malloc(buflen); for(p1=buf,p2=dir;*p2;p2++) *p1++=*p2; /* check if last copied char is '/', and if not then addit */ if(*(p1-1)!='/') *p1++='/'; *p1='\0'; for(p2=name;*p2;p2++) *p1++=*p2; *p1='\0'; /* TODO: how should the search be done ? */ /* if suffix is specified, then always use the suffix */ peon=p1; /* pointer to end of name without suffix */ if(suffix!=NULL) { for(p2=suffix;*p2;p2++) *p1++=*p2; *p1='\0'; debugVerbose("include: looking for file with suffix %s\n",suffix); if(fileExists(buf)) goto out_found; } /* look for file without suffix */ *peon='\0'; /* terminate string in buf */ debugVerbose("include: looking for without suffix:%s\n",name); if(fileExists(buf)) goto out_found; /* file not found */ free(buf); return 0; out_found:; /* free(buf); dont free just pass buf */ scannerContext->ppreturn->type=LIT_INCLUDE_FILE_NAME; scannerContext->ppreturn->string=buf; return 1; }
ssize_t pollAndRead(int fd, int timeout, char* cp_buffer, ssize_t num) { struct pollfd poll_fd; ssize_t i = 0; ssize_t in_size = 0; int i_poll_result = 0; poll_fd.fd = fd; poll_fd.events = POLLIN; poll_fd.revents = 0; // Poll for every byte for(i=0; i<num; ++i) { i_poll_result = poll(&poll_fd, 1, timeout); if (i_poll_result == -1) { debugVerbose(FILEHANDLING, "I/O error during poll.\n"); secAbort(); } else if (i_poll_result == 0) { debugVerbose(FILEHANDLING, "poll timed out\n"); return EXIT_FAILURE; } // Evaluate poll if((poll_fd.revents & ~POLLIN && !(poll_fd.revents & POLLIN))) break; if(!(poll_fd.revents & POLLIN)) break; // Read 1 Byte in_size= read(fd, &cp_buffer[i], 1); if (in_size < 0) { debugVerbose(FILEHANDLING, "I/O error on inbound file.\n"); secAbort(); } else if (in_size == 0) { break; } } return i; }
int findFileInDirList(char *dirList, char *name) { char * buf=malloc(512); char * p1,*p2; int isOK; if (!buf) error("Internal compiler error: out of mem"); debugParserpp("include findFileInDirList: dirlist %s, name %s\n",dirList,name); debugVerbose("include: Looking for file %s in directory list %s\n",name,dirList); /* the separator is either ':' or ';' */ for(isOK=0,p1=buf,p2=dirList;*p2;p2++) { if(*p2==':' || *p2==';') { // TODO also check last dir list ! *(p2+1)=='\0' *p1++='\0'; debugParserpp("include findFileInDirList: buf %s, name %s\n",buf,name); isOK=findFileInDir(buf,name); if(isOK) goto out_found; *buf='\0'; p1=buf; } else { /* TODO: check length of buf, and if >512 allocate larger */ *p1++=*p2; } } goto out_not_found; out_found: ; debugVerbose("include: found the file %s in path %s\n",name,buf); free(buf); return 1; out_not_found:; free(buf); return 0; }
/** * * return 0 File not found * 1 File found * * if the file is found the return area is set as follows: * scannerContext->ppreturn->type=LIT_INCLUDE_FILE_NAME; * scannerContext->ppreturn->string=<name of file>;; * * * * */ int findFile(char *name) { char defaultSearchDirs[]= "./:./include"; option_i=scannerContext->ppp->includePath; option_isuffix=scannerContext->ppp->includeSuffix; char *pathToUse; int isOK=0; if (!isOK&&option_i!=NULL) { /* if option -I is specified, look there */ debugVerbose("include: looking in compiler option -I%s\n",option_i); isOK=findFileInDirList(option_i,name); } if(!isOK) { /* look in default directories */ debugVerbose("include: looking in default search dirs: %s\n",defaultSearchDirs); isOK=findFileInDirList(defaultSearchDirs,name); } if(!isOK) { /* look in directory list PL1SYSLIB */ pathToUse = getenv("PL1SYSLIB"); if(pathToUse) { debugVerbose("include: looking in environment variable PL1SYSLIB: %s\n",pathToUse); isOK=findFileInDirList(pathToUse,name); } else isOK=0; } return isOK; }
int fileExists(char *fullname) { debugVerbose("include: Checking existence of file %s\n",fullname); FILE *input = fopen(fullname, "r"); if(input==NULL) { if(errno!=ENOENT) { /* only show detailed message if different from not found. */ perror(fullname); debugParserpp("include: Could not open file %s, errno %i ...\n",fullname,errno); } return 0; } fclose(input); return 1; }
int findEnvFile(char *env, char *name) { char *pathToUse; int isOK=0; if(!isOK) { /* look in directory list contained in environment variable */ pathToUse = getenv(env); debugVerbose("include: looking in environment variable %s: %s\n",env,pathToUse); isOK=findFileInDirList(pathToUse,name); } /* TODO: should the default search be performed if search in env fails ? */ /* if(!isOK) * isOK=findFile(name); */ return isOK; }
int AoEPreferences::SetSettingsInKEXT(void) { int nRet; nRet = m_pInterface->connect_to_driver(); if ( nRet ) { debugVerbose("Unable to connect to driver\n"); return nRet; } nRet = m_pInterface->set_preference_settings(&m_PreferenceData); if ( nRet ) { debugError("Unable to set settings in driver\n"); return nRet; } m_pInterface->disconnect(); return 0; }
void processStaticFile(const char* ccp_path) { FILE* file = NULL; int i_fd = -1; struct stat stat_buffer; char* cp_content_type = NULL; int i_content_length = 0; int i_success = 0; if(ccp_path == NULL) { debugVerbose(STATIC_FILE, "Error, no file path specified.\n"); secExit(STATUS_INTERNAL_SERVER_ERROR); } if(lstat(ccp_path, &stat_buffer) < 0) { debugVerbose(STATIC_FILE, "Opening file %s failed: %d\n", ccp_path, errno); secExit(STATUS_INTERNAL_SERVER_ERROR); } i_content_length = stat_buffer.st_size; file = fopen(ccp_path, "r"); if(file == NULL) { debugVerbose(STATIC_FILE, "Opening file %s failed: %d\n", ccp_path, errno); secExit(STATUS_INTERNAL_SERVER_ERROR); } i_fd = fileno(file); if(i_fd < 0) { debugVerbose(STATIC_FILE, "Retreiving a file descriptor from file pointer failed.\n"); secExit(STATUS_INTERNAL_SERVER_ERROR); } cp_content_type = parseExtension(ccp_path); i_success = sendHTTPResponseHeaderExplicit("200 OK", cp_content_type, i_content_length); if(i_success == EXIT_FAILURE) { debugVerbose(STATIC_FILE, "Sending header failed.\n"); secExit(STATUS_CANCEL); } debugVerbose(STATIC_FILE, "Sent HTTP response header to client.\n"); if(e_used_method != HEAD) { i_success = writeFileTo(i_fd, STDOUT_FILENO); if(i_success == EXIT_FAILURE) { debugVerbose(STATIC_FILE, "Sending file failed.\n"); fclose(file); secExit(STATUS_CANCEL); } debugVerbose(STATIC_FILE, "Sent file to client.\n"); } if(fclose(file) != 0) { //Everything is finished, here, no need to do something special debugVerbose(STATIC_FILE, "Could not close file.\n"); } }
/** tiniweb main routine * @param argc number of commandline arguments * @param argv arguments itself * @return tiniweb return value */ int main(int argc, char** argv) { int c = 0; int i_option_index = 0; bool b_static = FALSE; char* cp_mapped_path = NULL; char* cp_path_to_htdigest_file = NULL; char* cp_search_path_root = NULL; bool b_digest_file_available = FALSE; bool b_authenticated = FALSE; // command line parsing: like done in example from // http://www.gnu.org/s/libc/manual/html_node/Getopt-Long-Option-Example.html while (1) { static struct option long_options[] = { { "web-dir", required_argument, 0, 0 }, { "cgi-dir", required_argument, 0, 1 }, { "cgi-timeout", required_argument, 0, 2 }, { "secret", required_argument, 0, 3}, { "verbose", no_argument, 0, 4 }, { 0, 0, 0, 0 } }; i_option_index = 0; c = getopt_long(argc, argv, "", long_options, &i_option_index); if (c == -1) break; switch (c) { case 0: scp_web_dir_ = secPrint2String("%s", optarg); debugVerbose(MAIN, "option web-dir used with argument: %s \n", scp_web_dir_); break; case 1: scp_cgi_dir_ = secPrint2String("%s",optarg); debugVerbose(MAIN, "option cgi-dir used with argument: %s \n", scp_cgi_dir_); break; case 2: debugVerbose(MAIN, "option cgi-timeout used with argument: %s \n", optarg); si_cgi_timeout_ = (int) strtol(optarg, NULL, 10); si_cgi_timeout_ *= 1000; break; case 3: scp_secret_ = secPrint2String("%s", optarg); debugVerbose(MAIN, "option secret used with argument: %s \n", scp_secret_); break; case 4: b_flag_verbose_ = TRUE; debugVerbose(MAIN, "switching to verbose mode \n"); break; default: debug(MAIN, "encountert unknown argument \n"); secExit(STATUS_CANCEL); break; } } if(!scp_cgi_dir_ || !scp_web_dir_ || !scp_secret_){ debug(MAIN, "Mandatory parameter missing\n"); debug(MAIN, "usage: ./tiniweb (--verbose) --web-dir <path> --cgi-dir <path> --secret <secret> (--cgi-timeout <msec>)\n"); secExit(STATUS_CANCEL); } if (performPathChecking(&scp_cgi_dir_, &scp_web_dir_) == FALSE) { debug(MAIN, "ERROR, Paths not valid!\n"); secExit(STATUS_CANCEL); } if(si_cgi_timeout_ < CGI_TIME_OUT_MIN) { debug(MAIN, "cgi-timeout is too short, using default value (%d)\n", CGI_TIME_OUT_MIN); si_cgi_timeout_ = CGI_TIME_OUT_MIN; } else if(si_cgi_timeout_ > CGI_TIME_OUT_MAX) { debug(MAIN, "cgi-timeout is too long, using default value (%d)\n", CGI_TIME_OUT_MAX); si_cgi_timeout_ = CGI_TIME_OUT_MAX; } debug(MAIN, "Argument parsing finished\n"); debugVerbose(MAIN, "WEB_DIR = %s \n", scp_web_dir_); debugVerbose(MAIN, "CGI_DIR = %s \n", scp_cgi_dir_); debugVerbose(MAIN, "SECRET = %s \n", scp_secret_); debugVerbose(MAIN, "CGI_TIMEOUT = %d \n", si_cgi_timeout_); debugVerbose(MAIN, "Switching stdin to non_blocking mode\n"); if(setNonblocking(STDIN_FILENO)) { debug(MAIN, "Switching stdin to non_blocking mode failed!\n"); secAbort(); } char* cp_header = retrieveHeader(STDIN_FILENO, STDIN_TIMEOUT); if(cp_header == NULL) { debug(MAIN,"STDIN has to talk to use! We don't like DoS\n"); secExit(STATUS_CANCEL); } http_norm *hnp_info = normalizeHttp(cp_header, FALSE); debugVerbose(MAIN, "Normalize finished \n"); parse(hnp_info); debugVerbose(MAIN, "Parsing finished \n"); if (mapRequestPath(&cp_mapped_path, &b_static) == FALSE) { secExit(STATUS_NOT_FOUND); } if (checkRequestPath(cp_mapped_path) == FALSE) { secExit(STATUS_NOT_FOUND); } cp_search_path_root = b_static ? scp_web_dir_ : scp_cgi_dir_; if (searchForHTDigestFile(cp_mapped_path, cp_search_path_root, &b_digest_file_available, &cp_path_to_htdigest_file) == EXIT_FAILURE) { // We found two .htdigest Files in the path! File is protected! secExit(STATUS_FORBIDDEN); } if (b_digest_file_available) { b_authenticated = authenticate(cp_path_to_htdigest_file); } if(b_authenticated == TRUE || b_digest_file_available == FALSE) { if(b_static == TRUE) { processStaticFile(cp_mapped_path); } else { setupEnvVarList(scp_web_dir_, cp_mapped_path, hnp_info, b_authenticated); processCGIScript(cp_mapped_path); } } secExit(STATUS_OK); return EXIT_SUCCESS; }
char* retrieveHeader(int fd, int timeout) { char* cp_header = NULL; ssize_t i = 0; ssize_t in_size = 0; bool b_gotnl = FALSE; bool b_gotcr = FALSE; // first of all allocated our big buffer cp_header = secCalloc(MAX_HEADER_SIZE + 1, sizeof(char)); for(i=0; i<MAX_HEADER_SIZE; ++i) { in_size = pollAndRead(fd, timeout, &cp_header[i], 1); // Error from file is never good if(in_size == EXIT_FAILURE) { debugVerbose(FILEHANDLING, "Got problems with our fds\n"); secFree(cp_header); return NULL; } // Header has to end with \n\n if(in_size == 0) { debugVerbose(NORMALISE, "Invalid Header delimiter detected\n"); secExit(STATUS_BAD_REQUEST); } // register a \r if(cp_header[i] == '\r') { b_gotcr = TRUE; continue; } // special things to do on \n if(cp_header[i] == '\n') { // replace previous \r by \n if(b_gotcr == TRUE) { cp_header[i-1] = '\n'; cp_header[i] = '\0'; --i; b_gotcr = FALSE; } // break up if we had found a previous \n, thats the only right way to get out here if(b_gotnl == TRUE) { ++i; break; } b_gotnl = TRUE; continue; } // if we found a non character or a single \r we will break if(isValid(cp_header, i) == EXIT_FAILURE || b_gotcr == TRUE) { debugVerbose(FILEHANDLING, "Detected invalid char while retrieving header\n"); secExit(STATUS_BAD_REQUEST); } b_gotnl = FALSE; b_gotcr = FALSE; } // Header is too large if(i == MAX_HEADER_SIZE) { debug(FILEHANDLING, "Too long header! We don't like to get overflowed, bye bye\n"); secExit(STATUS_BAD_REQUEST); } cp_header[i] = '\0'; return secRealloc(cp_header, (i + 1) * sizeof(char)); }