int winscp_regular_request(char *request) { /* * winscp uses one of two requests to terminate each command. * we must determine which (if any) is terminating this request. fun! */ char *new_request=NULL; int retval=0; int retzero=1; new_request=strend(request, WINSCP_EOF_REQ_ZERO); if (NULL == new_request) { retzero=0; new_request=strend(request, WINSCP_EOF_REQ_STATUS); if (NULL == new_request) { new_request=strend(request, WINSCP_EOF_REQ_RETVAL); if (NULL == new_request) { printf ("command wasn't terminated with %s, %s or %s\n", WINSCP_EOF_REQ_RETVAL, WINSCP_EOF_REQ_ZERO, WINSCP_EOF_REQ_STATUS); return(-1); /* bogus termination */ } } } /* * here is where we fool winscp clients into believing we are a real shell */ if ((exact_match(new_request, "echo \"$status\"")) || (exact_match(new_request, "echo \"$?\""))) { printf ("0\n"); fflush(stdout); } /* * ignore unalias and unset commands */ else if ((NULL!=strbeg(new_request,"unset ")) || (NULL!=strbeg(new_request,"unalias "))) retval=0; else { retval=process_ssh_request(new_request); if (retzero) /* ignore actual retval if winscp wants us to */ retval=0; } free(new_request); return(retval); }
eParserSymbol parse_get_symbol( char *pszString, uint32_t *new_offset ) { uint32_t symIndex; uint32_t offset = 0; while ( isspace( pszString[offset] ) ) offset++; if ( pszString[offset] == '\0' ) { (*new_offset) = offset; return SYM_END; } for ( symIndex = 0; ; symIndex++ ) { if ( g_parseTable[symIndex].symbol == SYM_NOTFOUND ) { (*new_offset) = offset; return SYM_NOTFOUND; } if ( strbeg( pszString+offset, g_parseTable[symIndex].text ) == 0 ) { offset += cgc_strlen( g_parseTable[symIndex].text ); (*new_offset) = offset; return g_parseTable[symIndex].symbol; } } (*new_offset) = offset; return SYM_NOTFOUND; }
enum irc_type irc_get_type(char *msg) { unsigned int i; for(i=0; ; i++) { if(i>=IRC_MSG_LEN) return T_OTHER; if(msg[i]=='\0') return T_OTHER; if(msg[i]==' ') break; } i++; if(strbeg(msg+i, "JOIN")) return T_JOIN; if(strbeg(msg+i, "PRIVMSG")) { if(msg[i+8]==conf.chan[0]) return T_CHAN; return T_MSG; } return T_OTHER; }
void irc_loop(void) { char buf[IRC_MSG_LEN]; while(1) { irc_read(buf); if(strbeg(buf, "PING")) { buf[1] = 'O'; irc_cmd(buf); } else mod_handle(buf); } }
int winscp_transit_request(char *request) { char *new_request=NULL; /* * for scp -t and scp -f commands, winscp preceeds each * command with a "begin-of-file" marker we need to * provide, everything after that can be handled by * winscp_regular_request. */ new_request=strbeg(request,WINSCP_BOF_REQ); if (NULL == new_request) { return(-1); /* improper transit cmd */ } printf ("%s\n",WINSCP_BOF); /* start transfer */ fflush(stdout); return(winscp_regular_request(new_request)); }
int process_ssh_request(char *request) { char **av, **tmp_av, **tenv; char *flat_request,*tmpstring, *tmprequest; char bad_winscp3str[] = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server exec sftp-server"; int retval; int reqlen=strlen(request); char **env = NULL; debug(LOG_DEBUG, "processing request: \"%s\"\n", request); tmprequest=strdup(request); #ifdef WINSCP_COMPAT bad_winscp3str[57]=10; bad_winscp3str[127]=10; if(strcmp(request,bad_winscp3str)==0) { /* * switch out the command to use, winscp wont know the difference */ free(tmprequest); tmprequest=strdup(PROG_SFTP_SERVER); syslog(LOG_DEBUG, "winscp3 compat correcting to: \"[%s]\"\n", PROG_SFTP_SERVER); } #endif #ifdef GFTP_COMPAT /* * gFTP compatibility hack */ if (NULL != (tmpstring=strbeg(request, "echo -n xsftp ; "))) { free(tmprequest); tmprequest=strdup(tmpstring); printf("xsftp"); fflush(stdout); } #endif #ifdef RESTRICTIVE_FILENAMES /* * we flat out reject special chars */ if (!valid_chars(tmprequest)) { debug(LOG_DEBUG, "rejected because of invalid chars (%s)", logstamp()); free(tmprequest); return(-1); } #endif #ifdef WINSCP_COMPAT if (strbeg(tmprequest,PROG_CD)) { char *destdir=(char *)malloc(reqlen); if (destdir == NULL) { perror("malloc"); exit(EXIT_FAILURE); } /* * well, now that scponly is a persistent shell * i have to maintain a $PWD. damn. * we're going to INSIST upon a double quote * encapsulated new directory to change to. */ if ((tmprequest[(reqlen-1)]=='"') && (tmprequest[3]=='"')) { bzero(destdir,reqlen); strncpy(destdir,&tmprequest[4],reqlen-5); debug(LOG_INFO, "chdir: %s (%s)", tmprequest, logstamp()); retval=chdir(destdir); free(destdir); free(tmprequest); return(retval); } syslog(LOG_ERR, "bogus chdir request: %s (%s)", tmprequest, logstamp()); free(tmprequest); return(-1); } #endif /* * convert request string to an arg_vector */ av = build_arg_vector(tmprequest); /* * clean any path info from request and substitute our known pathnames */ av[0] = substitute_known_path(av[0]); /* * we only process wildcards for scp commands */ #ifdef ENABLE_WILDCARDS #ifdef ENABLE_SCP2 if (exact_match(av[0],PROG_SCP)) av = expand_wildcards(av); #endif #endif /* * check for a compile time chdir configuration */ #ifdef ENABLE_DEFAULT_CHDIR if (exact_match(av[0],PROG_SFTP_SERVER)) { syslog(LOG_INFO, "changing initial directory to %s", DEFAULT_CHDIR); chdir(DEFAULT_CHDIR); } #endif flat_request = flatten_vector(av); /* * Use a temp arg vector since getopt will permute the command line arguments * for anything that it does not know about. If all rsync options are well * defined this isn't necessary. */ tmp_av = build_arg_vector(flat_request); if(check_dangerous_args(tmp_av)) { syslog(LOG_ERR, "requested command (%s) tried to use disallowed argument (%s))", flat_request, logstamp()); exit(EXIT_FAILURE); } discard_vector(tmp_av); if (valid_arg_vector(av)) { /* * Unison needs the HOME environment variable be set to the directory * where the .unison directory resides. */ #ifdef USE_SAFE_ENVIRONMENT safeenv[0] = NULL; filter_allowed_env_vars(); tenv = safeenv; if (debuglevel) { while (NULL != *tenv) { syslog(LOG_DEBUG, "Environment contains \"%s\"", *tenv++); } } env = safeenv; #endif #ifdef UNISON_COMPAT /* the HOME environment variable should have been set above, but I need to make sure * that it's value as read from the environment is replaced with the actual value * as it exists within the chroot, which is what the applications will expect to see. */ if (replace_env_entry("HOME",homedir) && (((strlen(homedir) + 6 ) > FILENAME_MAX) || !mysetenv("HOME",homedir))) { syslog(LOG_ERR, "could not set HOME environment variable (%s)", logstamp()); exit(EXIT_FAILURE); } debug(LOG_DEBUG, "set non-chrooted HOME environment variable to %s (%s)", homedir, logstamp()); #endif syslog(LOG_INFO, "running: %s (%s)", flat_request, logstamp()); #ifdef WINSCP_COMPAT if (winscp_mode) { int status=0; if (fork() == 0) retval=execve(av[0],av,env); else { wait(&status); fflush(stdout); fflush(stderr); discard_vector(av); #ifdef USE_SAFE_ENVIRONMENT discard_child_vectors(safeenv); #endif free(flat_request); free(tmprequest); return(WEXITSTATUS(status)); } } else #endif { debug(LOG_DEBUG, "about to exec \"%s\" (%s)", av[0], logstamp()); retval=execve(av[0],av,env); } syslog(LOG_ERR, "failed: %s with error %s(%u) (%s)", flat_request, strerror(errno), errno, logstamp()); free(flat_request); discard_vector(av); #ifdef USE_SAFE_ENVIRONMENT discard_child_vectors(safeenv); #endif #ifdef WINSCP_COMPAT if (winscp_mode) { free(tmprequest); return(-1); } else #endif exit(errno); } /* * reaching this point in the code means the request isnt one of * our accepted commands */ if (debuglevel) { if (exact_match(flat_request,tmprequest)) syslog (LOG_ERR, "denied request: %s [%s]", tmprequest, logstamp()); else syslog (LOG_ERR, "denied request: %s (resolved to: %s) [%s]", tmprequest, flat_request, logstamp()); } free(flat_request); #ifdef WINSCP_COMPAT if (winscp_mode) { printf ("command not permitted by scponly\n"); free(tmprequest); return(-1); } else #endif exit(EXIT_FAILURE); }