int main(int argc, char *argv[]) { MyString my_full_name; const char *full_name; char* pw = NULL; struct StoreCredOptions options; int result = FAILURE_ABORTED; bool pool_password_arg = false; bool pool_password_delete = false; Daemon *daemon = NULL; char *credd_host; MyName = condor_basename(argv[0]); // load up configuration file myDistro->Init( argc, argv ); config(); if (!parseCommandLine(&options, argc, argv)) { goto cleanup; } // if -h was given, just print usage if (options.help || (options.mode == 0)) { usage(); goto cleanup; } #if !defined(WIN32) // if the -f argument was given, we just want to prompt for a password // and write it to a file (in our weirdo XORed format) // if (options.password_file != NULL) { if (options.pw[0] == '\0') { pw = get_password(); printf("\n"); } else { pw = strnewp(options.pw); SecureZeroMemory(options.pw, MAX_PASSWORD_LENGTH + 1); } result = write_password_file(options.password_file, pw); SecureZeroMemory(pw, strlen(pw)); if (result != SUCCESS) { fprintf(stderr, "error writing password file: %s\n", options.password_file); } goto cleanup; } #endif // determine the username to use if ( strcmp(options.username, "") == 0 ) { // default to current user and domain char* my_name = my_username(); char* my_domain = my_domainname(); my_full_name.formatstr("%s@%s", my_name, my_domain); if ( my_name) { free(my_name); } if ( my_domain) { free(my_domain); } my_name = my_domain = NULL; } else if (strcmp(options.username, POOL_PASSWORD_USERNAME) == 0) { #if !defined(WIN32) // we don't support querying the pool password on UNIX // (since it is not possible to do so through the // STORE_POOL_CRED command) if (options.mode == QUERY_MODE) { fprintf(stderr, "Querying the pool password is not supported.\n"); goto cleanup; } #endif // append the correct domain name if we're using the pool pass // we first try POOL_PASSWORD_DOMAIN, then UID_DOMAIN pool_password_arg = true; char *domain; if ((domain = param("SEC_PASSWORD_DOMAIN")) == NULL) { if ((domain = param("UID_DOMAIN")) == NULL) { fprintf(stderr, "ERROR: could not domain for pool password\n"); goto cleanup; } } my_full_name.formatstr(POOL_PASSWORD_USERNAME "@%s", domain); free(domain); } else { // username was specified on the command line my_full_name += options.username; } full_name = my_full_name.Value(); printf("Account: %s\n\n", full_name); // determine where to direct our command daemon = NULL; credd_host = NULL; if (options.daemonname != NULL) { if (pool_password_arg && (options.mode != QUERY_MODE)) { // daemon named on command line; go to master for pool password //printf("sending command to master: %s\n", options.daemonname); daemon = new Daemon(DT_MASTER, options.daemonname); } else { // daemon named on command line; go to schedd for user password //printf("sending command to schedd: %s\n", options.daemonname); daemon = new Daemon(DT_SCHEDD, options.daemonname); } } else if (!pool_password_arg && ((credd_host = param("CREDD_HOST")) != NULL)) { // no daemon given, use credd for user passwords if CREDD_HOST is defined // (otherwise, we use the local schedd) //printf("sending command to CREDD: %s\n", credd_host); daemon = new Daemon(DT_CREDD); } else { //printf("sending command to local daemon\n"); } // flag the case where we're deleting the pool password if (pool_password_arg && (options.mode == DELETE_MODE)) { pool_password_delete = true; } switch (options.mode) { case ADD_MODE: case DELETE_MODE: if (!pool_password_delete) { if ( strcmp(options.pw, "") == 0 ) { // get password from the user. pw = get_password(); printf("\n\n"); } else { // got the passwd from the command line. pw = strnewp(options.pw); SecureZeroMemory(options.pw, MAX_PASSWORD_LENGTH); } } if ( pw || pool_password_delete) { result = store_cred(full_name, pw, options.mode, daemon); if ((result == FAILURE_NOT_SECURE) && goAheadAnyways()) { // if user is ok with it, send the password in the clear result = store_cred(full_name, pw, options.mode, daemon, true); } if (pw) { SecureZeroMemory(pw, strlen(pw)); delete[] pw; } } break; case QUERY_MODE: result = queryCredential(full_name, daemon); break; #if defined(WIN32) case CONFIG_MODE: return interactive(); break; #endif default: fprintf(stderr, "Internal error\n"); goto cleanup; } // output result of operation switch (result) { case SUCCESS: if (options.mode == QUERY_MODE) { printf("A credential is stored and is valid.\n"); } else { printf("Operation succeeded.\n"); } break; case FAILURE: printf("Operation failed.\n"); if (pool_password_arg && (options.mode != QUERY_MODE)) { printf(" Make sure you have CONFIG access to the target Master.\n"); } else { printf(" Make sure your ALLOW_WRITE setting includes this host.\n"); } break; case FAILURE_BAD_PASSWORD: if (options.mode == QUERY_MODE) { printf("A credential is stored, but it is invalid. " "Run 'condor_store_cred add' again.\n"); } else { printf("Operation failed: bad password.\n"); } break; case FAILURE_NOT_FOUND: if (options.mode == QUERY_MODE) { printf("No credential is stored.\n"); } else { printf("Operation failed: username not found.\n"); } break; case FAILURE_NOT_SECURE: case FAILURE_ABORTED: printf("Operation aborted.\n"); break; case FAILURE_NOT_SUPPORTED: printf("Operation failed.\n" " The target daemon is not running as SYSTEM.\n"); break; default: fprintf(stderr, "Operation failed: unknown error code\n"); } cleanup: if (options.daemonname) { delete[] options.daemonname; } if (daemon) { delete daemon; } if ( result == SUCCESS ) { return 0; } else { return 1; } }
int store_cred_service(const char *user, const char *pw, int mode) { const char *at = strchr(user, '@'); if ((at == NULL) || (at == user)) { dprintf(D_ALWAYS, "store_cred: malformed user name\n"); return FAILURE; } if (( (size_t)(at - user) != strlen(POOL_PASSWORD_USERNAME)) || (memcmp(user, POOL_PASSWORD_USERNAME, at - user) != 0)) { dprintf(D_ALWAYS, "store_cred: only pool password is supported on UNIX\n"); return FAILURE; } char *filename; if (mode != QUERY_MODE) { filename = param("SEC_PASSWORD_FILE"); if (filename == NULL) { dprintf(D_ALWAYS, "store_cred: SEC_PASSWORD_FILE not defined\n"); return FAILURE; } } int answer; switch (mode) { case ADD_MODE: { answer = FAILURE; size_t pw_sz = strlen(pw); if (!pw_sz) { dprintf(D_ALWAYS, "store_cred_service: empty password not allowed\n"); break; } if (pw_sz > MAX_PASSWORD_LENGTH) { dprintf(D_ALWAYS, "store_cred_service: password too large\n"); break; } priv_state priv = set_root_priv(); answer = write_password_file(filename, pw); set_priv(priv); break; } case DELETE_MODE: { priv_state priv = set_root_priv(); int err = unlink(filename); set_priv(priv); if (!err) { answer = SUCCESS; } else { answer = FAILURE_NOT_FOUND; } break; } case QUERY_MODE: { char *password = getStoredCredential(POOL_PASSWORD_USERNAME, NULL); if (password) { answer = SUCCESS; SecureZeroMemory(password, MAX_PASSWORD_LENGTH); free(password); } else { answer = FAILURE_NOT_FOUND; } break; } default: dprintf(D_ALWAYS, "store_cred_service: unknown mode: %d\n", mode); answer = FAILURE; } // clean up after ourselves if (mode != QUERY_MODE) { free(filename); } return answer; }