TEST(fv_converter, key_matcher) { ASSERT_TRUE(exact_match("hoge").match("hoge")); ASSERT_FALSE(exact_match("hoge").match("foo")); ASSERT_TRUE(prefix_match("ho").match("hoge")); ASSERT_TRUE(prefix_match("hoge").match("hoge")); ASSERT_TRUE(prefix_match("").match("hoge")); ASSERT_FALSE(prefix_match("hogehgoe").match("hoge")); ASSERT_TRUE(suffix_match("ge").match("hoge")); ASSERT_TRUE(suffix_match("hoge").match("hoge")); ASSERT_TRUE(suffix_match("").match("hoge")); ASSERT_FALSE(suffix_match("hogehgoe").match("hoge")); }
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); }
// ./lect01 abacabadabacabaeabacabadabacabafabacabadabacabaeabacabadabacabagabacabadabacabaeabacabadabacabafabacabadabacabaeabacabadabacaba llolkloll // ./lect01 abacabadabacabaeabacabadabacabafabacabadabacabaeabacabadabacabagabacabadabacabaeabacabadabacabafabacabadabacabaeabacabadabacaba abadaba // gcc -O3 lect01.c -o lect01 int main(int argc, char const *argv[]) { for( int i = argc ; i-- ; ) { printf( "%s\n", argv[ i ] ); size_t *b = boundary( argv[ i ], strlen( argv[ i ] ) ); for( int j = 0 ; j < strlen( argv[ i ] ) ; ++j ) printf("%2d ", b[ j ] ); printf( "\n" ); free( b ); } size_t *b = boundary( "participate in parachute", 24 ); for( int j = 0 ; j < 24 ; ++j ) printf("%c %2d\n", "participate in parachute"[ j ], b[ j ] ); printf( "\n" ); free( b ); // Do some matching match_t *matches = exact_match( argv[ 1 ], strlen( argv[ 1 ] ), argv[ 2 ], strlen( argv[ 2 ] ) ); for( size_t m = 0 ; m < matches->nMatches ; ++m ) { printf("%d\n", matches->match[ m ] ); } free( matches ); return 0; }
void * delete_match_strict_entry( struct ofp_match match, uint16_t priority ) { if ( _match_table_head == NULL ) { die( "match table is not initialized." ); } pthread_mutex_lock( _match_table_head->mutex ); void *data = NULL; if ( exact_match( &match ) ) { data = delete_exact_match_strict_entry( _match_table_head->exact_table, &match ); } else { // wildcards flags are set data = delete_wildcards_match_strict_entry( &_match_table_head->wildcards_table, &match, priority ); } pthread_mutex_unlock( _match_table_head->mutex ); return data; }
bool update_match_entry( struct ofp_match match, uint16_t priority, void *data ) { if ( _match_table_head == NULL ) { die( "match table is not initialized." ); } pthread_mutex_lock( _match_table_head->mutex ); bool result; if ( exact_match( &match ) ) { result = update_exact_match_entry( _match_table_head->exact_table, &match, data ); } else { // wildcards flags are set result = update_wildcards_match_entry( _match_table_head->wildcards_table, &match, priority, data ); } pthread_mutex_unlock( _match_table_head->mutex ); return result; }
void * lookup_match_strict_entry( struct ofp_match match, uint16_t priority ) { if ( _match_table_head == NULL ) { die( "match table is not initialized." ); } pthread_mutex_lock( _match_table_head->mutex ); match_entry *entry; if ( exact_match( &match ) ) { entry = lookup_exact_match_strict_entry( _match_table_head->exact_table, &match ); } else { entry = lookup_wildcards_match_strict_entry( _match_table_head->wildcards_table, &match, priority ); } void *data = ( entry != NULL ? entry->data : NULL ); pthread_mutex_unlock( _match_table_head->mutex ); return data; }
bool contains_word( const char*& argument, const char* word, char* arg ) { const char* s1 = argument; const char* s2; for( ; *s1 != '\0'; ) { if( exact_match( s2 = s1, word ) ) { for( ; s1 != argument && *(s1-1) == ' '; s1-- ); memcpy( arg, argument, s1-argument ); arg[s1-argument] = '\0'; argument = s2; return TRUE; } for( ; *s1 != '\0' && *s1 != ' '; s1++ ); for( ; *s1 == ' '; s1++ ); } return FALSE; }
void do_shedit( char_data* ch, char* argument ) { char buf [MAX_STRING_LENGTH ]; mob_data* keeper; shop_data* shop; char_data* victim; species_data* species; int number; for( shop = shop_list; shop != NULL; shop = shop->next ) if( ch->in_room == shop->room ) break; if( *argument != '\0' && !can_edit( ch, ch->in_room ) ) return; if( exact_match( argument, "new" ) ) { if( shop != NULL ) { send( ch, "There is already a shop here.\r\n" ); return; } shop = new shop_data; shop->room = ch->in_room; shop->custom = NULL; shop->keeper = -1; shop->repair = 0; shop->materials = 0; shop->buy_type[0] = 0; shop->buy_type[1] = 0; shop->next = shop_list; shop_list = shop; send( ch, "New shop created here.\r\n" ); return; } if( shop == NULL ) { send( ch, "There is no shop associated with this room.\r\n" ); return; } if( *argument == '\0' ) { species = get_species( shop->keeper ); sprintf( buf, "Shop Keeper: %s [ Vnum: %d ]\r\n\r\n", ( species == NULL ? "none" : species->descr->name ), shop->keeper ); sprintf( buf+strlen( buf ), "Repair: %d\r\n\r\n", shop->repair ); send( buf, ch ); return; } if( exact_match( argument, "delete" ) ) { remove( shop_list, shop ); for( int i = 0; i < mob_list; i++ ) if( mob_list[i]->pShop == shop ) mob_list[i]->pShop = NULL; send( ch, "Shop deleted.\r\n" ); return; } if( matches( argument, "keeper" ) ) { if( ( victim = one_character( ch, argument, "set keepr", ch->array ) ) == NULL ) return; if( ( keeper = mob( victim ) ) == NULL ) { send( ch, "Players can not be shop keepers.\r\n" ); return; } shop->keeper = keeper->species->vnum; keeper->pShop = shop; send( ch, "Shop keeper set to %s.\r\n", keeper->descr->name ); return; } if( matches( argument, "repair" ) ) { if( ( number = atoi( argument ) ) < 0 || number > 10 ) { send( ch, "A shop's repair level must be between 0 and 10.\r\n" ); return; } shop->repair = number; send( ch, "The shop's repair level is set to %d.\r\n", number ); } }
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); }
int process_pre_chroot_request(char ** av) { char *flat_request = NULL; char *env[2] = { NULL, NULL }; int retval = -1; /* revert to real user so I'm not changing the passwd as root */ debug(LOG_DEBUG, "handling pre-chroot request"); debug(LOG_DEBUG, "setting uid to %u", getuid()); if (-1==(seteuid(getuid()))) { syslog (LOG_ERR, "couldn't revert to my real uid. seteuid: %m"); exit(EXIT_FAILURE); } av[0] = substitute_known_path(av[0]); flat_request = flatten_vector(av); /* * sanity check, substitute_known_path should have given the exact path, * ONLY execute if an exact match was found */ if ( #ifdef PASSWD_COMPAT (!exact_match(av[0], PROG_PASSWD)) #else 1 #endif #ifdef QUOTA_COMPAT && (!exact_match(av[0], PROG_QUOTA)) #endif ) { syslog(LOG_ERR, "Invalid pre-chroot request attempted: '%s' [%s]", av[0], logstamp()); exit(EXIT_FAILURE); } if(check_dangerous_args(av)) { syslog(LOG_ERR, "requested command (%s) tried to use disallowed argument [%s])", flat_request, logstamp()); exit(EXIT_FAILURE); } if (valid_arg_vector(av)) { int status = 0; debug(LOG_DEBUG, "about to fork (%s) [%s]",flat_request,logstamp()); if (fork() == 0) retval=execve(av[0],av,env); else { wait(&status); fflush(stdout); fflush(stderr); free(flat_request); debug(LOG_DEBUG, "forked child returned... [%s]",logstamp()); return WEXITSTATUS(status); } } else { syslog(LOG_ERR, "invalid argument vector (%s) [%s]", flat_request,logstamp()); free(flat_request); exit(EXIT_FAILURE); } return retval; }
int main (int argc, char **argv) { FILE *debugfile; int logopts = LOG_PID|LOG_NDELAY; int chars_read = 0; #ifdef CHROOT_CHECKDIR struct stat homedirstat; #endif /* * set debuglevel. any nonzero number will result in debugging info to log */ if (NULL!=(debugfile=fopen(DEBUGFILE,"r"))) { chars_read = fscanf(debugfile,"%d",&debuglevel); if (chars_read < 1) debuglevel = 0; fclose(debugfile); } #ifndef UNIX_COMPAT if (debuglevel > 1) /* debuglevel 1 will still log to syslog */ logopts |= LOG_PERROR; #endif #ifdef UNIX_COMPAT openlog(PACKAGE_NAME, logopts, LOG_AUTH); #elif IRIX_COMPAT openlog(PACKAGE_NAME, logopts, LOG_AUTH); #else if (debuglevel > 1) /* debuglevel 1 will still log to syslog */ logopts |= LOG_PERROR; openlog(PACKAGE_NAME, logopts, LOG_AUTHPRIV); #endif if (debuglevel > 0) debug = syslog; else debug = noop_syslog; #ifdef HAVE_GETOPT_H scponly_getopt_long = getopt_long; #else debug(LOG_INFO, "using netbsd's bundled getopt_long"); scponly_getopt_long = netbsd_getopt_long; #endif #ifdef CHROOTED_NAME /* * is this a chroot'ed scponly installation? */ #ifdef WINSCP_COMPAT if ((argc==3 && (0==strncmp(argv[0],CHROOTED_NAME,FILENAME_MAX)) ) || ( argc==1 && (0==strncmp(&argv[0][1],CHROOTED_NAME,FILENAME_MAX )))) #else if (0==strncmp(argv[0],CHROOTED_NAME,FILENAME_MAX)) #endif { debug(LOG_INFO, "chrooted binary in place, will chroot()"); chrooted=1; } #endif /* CHROOTED_NAME */ if (debuglevel) { int i; syslog(LOG_DEBUG, "%d arguments in total.", argc); for (i=0;i<argc;i++) syslog(LOG_DEBUG, "\targ %u is %s", i, argv[i]); } #ifdef UNIX_COMPAT debug(LOG_DEBUG, "opened log at LOG_AUTH, opts 0x%08x", logopts); #else debug(LOG_DEBUG, "opened log at LOG_AUTHPRIV, opts 0x%08x", logopts); #endif if (getuid()==0) { syslog(LOG_ERR, "root login denied [%s]", logstamp()); exit(EXIT_FAILURE); } #ifdef WINSCP_COMPAT if ((argc!=3) && (argc!=1)) #else if (argc!=3) #endif { debug(LOG_ERR, "incorrect number of args"); exit(EXIT_FAILURE); } if (!get_uservar()) { syslog(LOG_ERR, "%s is misconfigured. contact sysadmin.", argv[0]); exit (EXIT_FAILURE); } #ifdef CHROOTED_NAME if (chrooted) { char **av = NULL; char *tmprequest = NULL; char *root_dir = chrootdir; char chdir_path[FILENAME_MAX]; strcpy(chrootdir, homedir); strcpy(chdir_path, "/"); while((root_dir = strchr(root_dir, '/')) != NULL) { if (strncmp(root_dir, "//", 2) == 0) { snprintf(chdir_path, FILENAME_MAX, "%s", root_dir + 1); /* make sure HOME will be set to something correct if used*/ debug(LOG_DEBUG, "Setting homedir to %s", chdir_path); strcpy(homedir, chdir_path); *root_dir = '\0'; break; } root_dir++; } #ifdef CHROOT_CHECKDIR bzero(&homedirstat, sizeof(struct stat)); if (-1 == stat(chrootdir, &homedirstat)) { syslog (LOG_ERR, "couldnt stat chroot dir: %s with errno %u", chrootdir, errno); exit(EXIT_FAILURE); } if (0 == (homedirstat.st_mode | S_IFDIR)) { syslog (LOG_ERR, "chroot dir is not a directory: %s", chrootdir); exit(EXIT_FAILURE); } if (homedirstat.st_uid != 0) { syslog (LOG_ERR, "chroot dir not owned by root: %s", chrootdir); exit(EXIT_FAILURE); } if (0 != (homedirstat.st_mode & S_IWOTH)) { syslog (LOG_ERR, "chroot dir writable by other: %s", chrootdir); exit(EXIT_FAILURE); } if (0 != (homedirstat.st_mode & S_IWGRP)) { syslog (LOG_ERR, "chroot dir writable by group: %s", chrootdir); exit(EXIT_FAILURE); } #endif /* already within CHROOTED_NAME block */ #if defined(PASSWD_COMPAT) || defined(QUOTA_COMPAT) /* * perhaps we need to refactor so we don't have to exit right * in the middle of the code, but we can't chroot and expect to be * able to change the password and have it be of any use unless * there is some additional process that scponly is unaware of * happening on the back end. */ tmprequest = strdup(argv[2]); av = build_arg_vector(tmprequest); free(tmprequest); if ( #ifdef PASSWD_COMPAT (exact_match(av[0],"passwd")) || (exact_match(av[0],PROG_PASSWD)) #else 0 #endif #ifdef QUOTA_COMPAT || (exact_match(av[0],"quota")) || (exact_match(av[0],PROG_QUOTA)) #endif ) { int status = process_pre_chroot_request(av); discard_vector(av); if (status) { syslog(LOG_ERR, "process_pre_chroot_request(%s) failed with code %i [%s]", argv[2],WEXITSTATUS(status),logstamp()); exit(EXIT_FAILURE); } debug(LOG_DEBUG, "scponly completed"); exit(EXIT_SUCCESS); } else { discard_vector(av); } #endif /* passwd or quota */ debug(LOG_DEBUG, "chrooting to dir: \"%s\"", chrootdir); if (-1==(chroot(chrootdir))) { debug(LOG_ERR, "chroot: %m"); syslog(LOG_ERR, "couldn't chroot to %s [%s]", chrootdir, logstamp()); exit(EXIT_FAILURE); } debug(LOG_DEBUG, "chdiring to dir: \"%s\"", chdir_path); if (-1==(chdir(chdir_path))) { debug(LOG_ERR, "chdir: %m"); syslog (LOG_ERR, "couldn't chdir to %s [%s]", chdir_path, logstamp()); exit(EXIT_FAILURE); } } #endif /* CHROOTED_NAME */ debug(LOG_DEBUG, "setting uid to %u", getuid()); if (-1==(seteuid(getuid()))) { syslog(LOG_ERR, "couldn't revert to my real uid. seteuid: %m"); exit(EXIT_FAILURE); } #ifdef WINSCP_COMPAT if (argc==1) { debug(LOG_DEBUG, "entering WinSCP compatibility mode [%s]",logstamp()); if (-1==process_winscp_requests()) { syslog(LOG_ERR, "failed WinSCP compatibility mode [%s]", logstamp()); exit(EXIT_FAILURE); } } #else if (0) {} /* placeholder */ #endif else if (-1==process_ssh_request(argv[2])) { syslog(LOG_ERR, "bad request: %s [%s]", argv[2], logstamp()); exit(EXIT_FAILURE); } debug(LOG_DEBUG, "scponly completed"); exit(EXIT_SUCCESS); }