KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_get_creds(krb5_context context, krb5_get_creds_opt opt, krb5_ccache ccache, krb5_const_principal inprinc, krb5_creds **out_creds) { krb5_kdc_flags flags; krb5_flags options; krb5_creds in_creds; krb5_error_code ret; krb5_creds **tgts; krb5_creds *try_creds; krb5_creds *res_creds; krb5_name_canon_iterator name_canon_iter = NULL; krb5_name_canon_rule_options rule_opts; int i; if (opt && opt->enctype) { ret = krb5_enctype_valid(context, opt->enctype); if (ret) return ret; } memset(&in_creds, 0, sizeof(in_creds)); in_creds.server = rk_UNCONST(inprinc); ret = krb5_cc_get_principal(context, ccache, &in_creds.client); if (ret) return ret; if (opt) options = opt->options; else options = 0; flags.i = 0; *out_creds = NULL; res_creds = calloc(1, sizeof(*res_creds)); if (res_creds == NULL) { krb5_free_principal(context, in_creds.client); return krb5_enomem(context); } if (opt && opt->enctype) { in_creds.session.keytype = opt->enctype; options |= KRB5_TC_MATCH_KEYTYPE; } /* Check for entry in ccache */ if (inprinc->name.name_type == KRB5_NT_SRV_HST_NEEDS_CANON) { ret = check_cc(context, options, ccache, &in_creds, res_creds); if (ret == 0) { *out_creds = res_creds; goto out; } } ret = krb5_name_canon_iterator_start(context, NULL, &in_creds, &name_canon_iter); if (ret) goto out; next_rule: ret = krb5_name_canon_iterate_creds(context, &name_canon_iter, &try_creds, &rule_opts); if (ret) return ret; if (name_canon_iter == NULL) { if (options & KRB5_GC_CACHED) ret = KRB5_CC_NOTFOUND; else ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } ret = check_cc(context, options, ccache, try_creds, res_creds); if (ret == 0) { *out_creds = res_creds; goto out; } else if(ret != KRB5_CC_END) { goto out; } if(options & KRB5_GC_CACHED) goto next_rule; if(rule_opts & KRB5_NCRO_USE_REFERRALS) flags.b.canonicalize = 1; else if(rule_opts & KRB5_NCRO_NO_REFERRALS) flags.b.canonicalize = 0; else flags.b.canonicalize = (options & KRB5_GC_CANONICALIZE) ? 1 : 0; if(options & KRB5_GC_USER_USER) { flags.b.enc_tkt_in_skey = 1; options |= KRB5_GC_NO_STORE; } if (options & KRB5_GC_FORWARDABLE) flags.b.forwardable = 1; if (options & KRB5_GC_NO_TRANSIT_CHECK) flags.b.disable_transited_check = 1; if (options & KRB5_GC_CONSTRAINED_DELEGATION) { flags.b.request_anonymous = 1; /* XXX ARGH confusion */ flags.b.constrained_delegation = 1; } tgts = NULL; ret = _krb5_get_cred_kdc_any(context, flags, ccache, try_creds, opt ? opt->self : 0, opt ? opt->ticket : 0, out_creds, &tgts); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); krb5_free_creds(context, tgts[i]); } free(tgts); if (ret == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN && !(rule_opts & KRB5_NCRO_SECURE)) goto next_rule; if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) store_cred(context, ccache, inprinc, *out_creds); out: if (ret) { krb5_free_creds(context, res_creds); ret = not_found(context, inprinc, ret); } krb5_free_principal(context, in_creds.client); krb5_free_name_canon_iterator(context, name_canon_iter); _krb5_debug(context, 5, "krb5_get_creds: ret = %d", ret); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_get_credentials_with_flags(krb5_context context, krb5_flags options, krb5_kdc_flags flags, krb5_ccache ccache, krb5_creds *in_creds, krb5_creds **out_creds) { krb5_error_code ret; krb5_name_canon_iterator name_canon_iter = NULL; krb5_name_canon_rule_options rule_opts; krb5_creds **tgts; krb5_creds *try_creds; krb5_creds *res_creds; int i; if (in_creds->session.keytype) { ret = krb5_enctype_valid(context, in_creds->session.keytype); if (ret) return ret; options |= KRB5_TC_MATCH_KEYTYPE; } *out_creds = NULL; res_creds = calloc(1, sizeof(*res_creds)); if (res_creds == NULL) return krb5_enomem(context); if (in_creds->server->name.name_type == KRB5_NT_SRV_HST_NEEDS_CANON) { ret = check_cc(context, options, ccache, in_creds, res_creds); if (ret == 0) { *out_creds = res_creds; return 0; } } ret = krb5_name_canon_iterator_start(context, NULL, in_creds, &name_canon_iter); if (ret) return ret; next_rule: krb5_free_cred_contents(context, res_creds); memset(res_creds, 0, sizeof (*res_creds)); ret = krb5_name_canon_iterate_creds(context, &name_canon_iter, &try_creds, &rule_opts); if (ret) goto out; if (name_canon_iter == NULL) { if (options & KRB5_GC_CACHED) ret = KRB5_CC_NOTFOUND; else ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } ret = check_cc(context, options, ccache, try_creds, res_creds); if (ret == 0) { *out_creds = res_creds; goto out; } else if(ret != KRB5_CC_END) { goto out; } if(options & KRB5_GC_CACHED) goto next_rule; if(options & KRB5_GC_USER_USER) flags.b.enc_tkt_in_skey = 1; if (flags.b.enc_tkt_in_skey) options |= KRB5_GC_NO_STORE; tgts = NULL; ret = _krb5_get_cred_kdc_any(context, flags, ccache, try_creds, NULL, NULL, out_creds, &tgts); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); krb5_free_creds(context, tgts[i]); } free(tgts); if (ret == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN && !(rule_opts & KRB5_NCRO_SECURE)) goto next_rule; if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) store_cred(context, ccache, in_creds->server, *out_creds); out: krb5_free_name_canon_iterator(context, name_canon_iter); if (ret) { krb5_free_creds(context, res_creds); return not_found(context, in_creds->server, ret); } return 0; }
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 queryCredential( const char* user, Daemon *d ) { return store_cred(user, NULL, QUERY_MODE, d); }
int addCredential( const char* user, const char* pw, Daemon *d ) { return store_cred(user, pw, ADD_MODE, d); }
int deleteCredential( const char* user, const char* pw, Daemon *d ) { return store_cred(user, pw, DELETE_MODE, d); }