int main( int argc, char *argv[] ) { char *arg; char **args = (char **)malloc(sizeof(char *)*(argc - 1)); // args int nArgs = 0; // number of args int i; char* cmd_str; DCCollector* pool = NULL; char* scheddName = NULL; char* scheddAddr = NULL; // Initialize our global variables has_constraint = false; myDistro->Init( argc, argv ); MyName = strrchr( argv[0], DIR_DELIM_CHAR ); if( !MyName ) { MyName = argv[0]; } else { MyName++; } cmd_str = strchr( MyName, '_'); // we match modes based on characters after the '_'. This means // 'condor_hold.exe' or 'condor_hold_wrapped' are all legal argv[0]'s // for condor_hold. if (cmd_str && strncasecmp( cmd_str, "_hold", strlen("_hold") ) == MATCH) { mode = JA_HOLD_JOBS; } else if ( cmd_str && strncasecmp( cmd_str, "_release", strlen("_release") ) == MATCH ) { mode = JA_RELEASE_JOBS; } else if ( cmd_str && strncasecmp( cmd_str, "_suspend", strlen("_suspend") ) == MATCH ) { mode = JA_SUSPEND_JOBS; } else if ( cmd_str && strncasecmp( cmd_str, "_continue", strlen("_continue") ) == MATCH ) { mode = JA_CONTINUE_JOBS; }else if ( cmd_str && strncasecmp( cmd_str, "_rm", strlen("_rm") ) == MATCH ) { mode = JA_REMOVE_JOBS; } else if( cmd_str && ! strncasecmp(cmd_str, "_vacate_job", strlen("_vacate_job")) ) { mode = JA_VACATE_JOBS; } else { // don't know what mode we're using, so bail. fprintf( stderr, "Unrecognized command name, \"%s\"\n", MyName ); usage(); } config(); if( argc < 2 ) { // We got no indication of what to act on fprintf( stderr, "You did not specify any jobs\n" ); usage(); } #if !defined(WIN32) install_sig_handler(SIGPIPE, SIG_IGN ); #endif for( argv++; (arg = *argv); argv++ ) { if( arg[0] == '-' ) { if (match_prefix(arg, "-debug")) { // dprintf to console dprintf_set_tool_debug("TOOL", 0); } else if (match_prefix(arg, "-constraint")) { args[nArgs] = arg; nArgs++; argv++; if( ! *argv ) { fprintf( stderr, "%s: -constraint requires another argument\n", MyName); exit(1); } args[nArgs] = *argv; nArgs++; ConstraintArg = true; } else if (match_prefix(arg, "-all")) { All = true; } else if (match_prefix(arg, "-addr")) { argv++; if( ! *argv ) { fprintf( stderr, "%s: -addr requires another argument\n", MyName); exit(1); } if( is_valid_sinful(*argv) ) { scheddAddr = strdup(*argv); if( ! scheddAddr ) { fprintf( stderr, "Out of memory!\n" ); exit(1); } } else { fprintf( stderr, "%s: \"%s\" is not a valid address\n", MyName, *argv ); fprintf( stderr, "Should be of the form " "<ip.address.here:port>\n" ); fprintf( stderr, "For example: <123.456.789.123:6789>\n" ); exit( 1 ); } } else if (match_prefix(arg, "-reason")) { argv++; if( ! *argv ) { fprintf( stderr, "%s: -reason requires another argument\n", MyName); exit(1); } actionReason = strdup(*argv); if( ! actionReason ) { fprintf( stderr, "Out of memory!\n" ); exit(1); } } else if (match_prefix(arg, "-subcode")) { argv++; if( ! *argv ) { fprintf( stderr, "%s: -subcode requires another argument\n", MyName); exit(1); } char *end = NULL; long code = strtol(*argv,&end,10); if( code == LONG_MIN || !end || *end || end==*argv ) { fprintf( stderr, "Invalid -subcode %s!\n", *argv ); exit(1); } holdReasonSubCode = strdup(*argv); ASSERT( holdReasonSubCode ); } else if (match_prefix(arg, "-forcex")) { if( mode == JA_REMOVE_JOBS ) { mode = JA_REMOVE_X_JOBS; } else { fprintf( stderr, "-forcex is only valid with condor_rm\n" ); usage(); } } else if (match_prefix(arg, "-fast")) { if( mode == JA_VACATE_JOBS ) { mode = JA_VACATE_FAST_JOBS; } else { fprintf( stderr, "-fast is only valid with condor_vacate_job\n" ); usage(); } } else if (match_prefix(arg, "-name")) { // use the given name as the schedd name to connect to argv++; if( ! *argv ) { fprintf( stderr, "%s: -name requires another argument\n", MyName); exit(1); } if( !(scheddName = get_daemon_name(*argv)) ) { fprintf( stderr, "%s: unknown host %s\n", MyName, get_host_part(*argv) ); exit(1); } } else if (match_prefix(arg, "-pool")) { // use the given name as the central manager to query argv++; if( ! *argv ) { fprintf( stderr, "%s: -pool requires another argument\n", MyName); exit(1); } if( pool ) { delete pool; } pool = new DCCollector( *argv ); if( ! pool->addr() ) { fprintf( stderr, "%s: %s\n", MyName, pool->error() ); exit(1); } } else if (match_prefix(arg, "-version")) { version(); } else if (match_prefix(arg, "-help")) { usage(0); } else { fprintf( stderr, "Unrecognized option: %s\n", arg ); usage(); } } else { if( All ) { // If -all is set, there should be no other // constraint arguments. usage(); } args[nArgs] = arg; nArgs++; UserJobIdArg = true; } } if( ! (All || nArgs) ) { // We got no indication of what to act on fprintf( stderr, "You did not specify any jobs\n" ); usage(); } if ( ConstraintArg && UserJobIdArg ) { fprintf( stderr, "You can't use both -constraint and usernames or job ids\n" ); usage(); } // Pick the default reason if the user didn't specify one if( actionReason == NULL ) { switch( mode ) { case JA_RELEASE_JOBS: actionReason = strdup("via condor_release"); break; case JA_REMOVE_X_JOBS: actionReason = strdup("via condor_rm -forcex"); break; case JA_REMOVE_JOBS: actionReason = strdup("via condor_rm"); break; case JA_HOLD_JOBS: actionReason = strdup("via condor_hold"); break; case JA_SUSPEND_JOBS: actionReason = strdup("via condor_suspend"); break; case JA_CONTINUE_JOBS: actionReason = strdup("via condor_continue"); break; default: actionReason = NULL; } } // We're done parsing args, now make sure we know how to // contact the schedd. if( ! scheddAddr ) { // This will always do the right thing, even if either or // both of scheddName or pool are NULL. schedd = new DCSchedd( scheddName, pool ? pool->addr() : NULL ); } else { schedd = new DCSchedd( scheddAddr ); } if( ! schedd->locate() ) { fprintf( stderr, "%s: %s\n", MyName, schedd->error() ); exit( 1 ); } // Special case for condor_rm -forcex: a configuration // setting can disable this functionality. The real // validation is done in the schedd, but we can catch // the most common cases here and give a useful error // message. if(mode == JA_REMOVE_X_JOBS) { if( mayUserForceRm() == false) { fprintf( stderr, "Remove aborted. condor_rm -forcex has been disabled by the administrator.\n" ); exit( 1 ); } } // Process the args so we do the work. if( All ) { handleAll(); } else { for(i = 0; i < nArgs; i++) { if( match_prefix( args[i], "-constraint" ) ) { i++; addConstraint( args[i] ); } else { procArg(args[i]); } } } // Deal with all the -constraint constraints handleConstraints(); // Finally, do the actual work for all our args which weren't // constraints... if( job_ids ) { CondorError errstack; ClassAd* result_ad = doWorkByList( job_ids, &errstack ); if (had_error) { fprintf( stderr, "%s\n", errstack.getFullText(true).c_str() ); } printNewMessages( result_ad, job_ids ); delete( result_ad ); } // If releasing jobs, and no errors happened, do a // reschedule command now. if ( mode == JA_RELEASE_JOBS && had_error == false ) { Daemon my_schedd(DT_SCHEDD, NULL, NULL); CondorError errstack; if (!my_schedd.sendCommand(RESCHEDULE, Stream::safe_sock, 0, &errstack)) { fprintf( stderr, "%s\n", errstack.getFullText(true).c_str() ); } } return had_error; }
int store_cred(const char* user, const char* pw, int mode, Daemon* d, bool force) { int result; int return_val; Sock* sock = NULL; // to help future debugging, print out the mode we are in static const int mode_offset = 100; static const char *mode_name[] = { ADD_CREDENTIAL, DELETE_CREDENTIAL, QUERY_CREDENTIAL #ifdef WIN32 , CONFIG_CREDENTIAL #endif }; dprintf ( D_ALWAYS, "STORE_CRED: In mode '%s'\n", mode_name[mode - mode_offset] ); // If we are root / SYSTEM and we want a local daemon, // then do the work directly to the local registry. // If not, then send the request over the wire to a remote credd or schedd. if ( is_root() && d == NULL ) { // do the work directly onto the local registry return_val = store_cred_service(user,pw,mode); } else { // send out the request remotely. // first see if we're operating on the pool password int cmd = STORE_CRED; char const *tmp = strchr(user, '@'); if (tmp == NULL || tmp == user || *(tmp + 1) == '\0') { dprintf(D_ALWAYS, "store_cred: user not in user@domain format\n"); return FAILURE; } if (((mode == ADD_MODE) || (mode == DELETE_MODE)) && ( (size_t)(tmp - user) == strlen(POOL_PASSWORD_USERNAME)) && (memcmp(POOL_PASSWORD_USERNAME, user, tmp - user) == 0)) { cmd = STORE_POOL_CRED; user = tmp + 1; // we only need to send the domain name for STORE_POOL_CRED } if (d == NULL) { if (cmd == STORE_POOL_CRED) { // need to go to the master for setting the pool password dprintf(D_FULLDEBUG, "Storing credential to local master\n"); Daemon my_master(DT_MASTER); sock = my_master.startCommand(cmd, Stream::reli_sock, 0); } else { dprintf(D_FULLDEBUG, "Storing credential to local schedd\n"); Daemon my_schedd(DT_SCHEDD); sock = my_schedd.startCommand(cmd, Stream::reli_sock, 0); } } else { dprintf(D_FULLDEBUG, "Starting a command on a REMOTE schedd\n"); sock = d->startCommand(cmd, Stream::reli_sock, 0); } if( !sock ) { dprintf(D_ALWAYS, "STORE_CRED: Failed to start command.\n"); dprintf(D_ALWAYS, "STORE_CRED: Unable to contact the REMOTE schedd.\n"); return FAILURE; } // for remote updates (which send the password), verify we have a secure channel, // unless "force" is specified if (((mode == ADD_MODE) || (mode == DELETE_MODE)) && !force && (d != NULL) && ((sock->type() != Stream::reli_sock) || !((ReliSock*)sock)->triedAuthentication() || !sock->get_encryption())) { dprintf(D_ALWAYS, "STORE_CRED: blocking attempt to update over insecure channel\n"); delete sock; return FAILURE_NOT_SECURE; } if (cmd == STORE_CRED) { result = code_store_cred(sock, const_cast<char*&>(user), const_cast<char*&>(pw), mode); if( result == FALSE ) { dprintf(D_ALWAYS, "store_cred: code_store_cred failed.\n"); delete sock; return FAILURE; } } else { // only need to send the domain and password for STORE_POOL_CRED if (!sock->code(const_cast<char*&>(user)) || !sock->code(const_cast<char*&>(pw)) || !sock->end_of_message()) { dprintf(D_ALWAYS, "store_cred: failed to send STORE_POOL_CRED message\n"); delete sock; return FAILURE; } } sock->decode(); result = sock->code(return_val); if( !result ) { dprintf(D_ALWAYS, "store_cred: failed to recv answer.\n"); delete sock; return FAILURE; } result = sock->end_of_message(); if( !result ) { dprintf(D_ALWAYS, "store_cred: failed to recv eom.\n"); delete sock; return FAILURE; } } // end of case where we send out the request remotely switch(mode) { case ADD_MODE: if( return_val == SUCCESS ) { dprintf(D_FULLDEBUG, "Addition succeeded!\n"); } else { dprintf(D_FULLDEBUG, "Addition failed!\n"); } break; case DELETE_MODE: if( return_val == SUCCESS ) { dprintf(D_FULLDEBUG, "Delete succeeded!\n"); } else { dprintf(D_FULLDEBUG, "Delete failed!\n"); } break; case QUERY_MODE: if( return_val == SUCCESS ) { dprintf(D_FULLDEBUG, "We have a credential stored!\n"); } else { dprintf(D_FULLDEBUG, "Query failed!\n"); } break; } if ( sock ) delete sock; return return_val; }