OM_uint32
_gsskrb5_appl_change_password(OM_uint32 *minor_status,
			      gss_name_t name,
			      const char *oldpw,
			      const char *newpw)
{
    krb5_data result_code_string, result_string;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_context context;
    krb5_principal principal = (krb5_principal)name;
    krb5_creds kcred;
    krb5_error_code ret;
    int result_code;

    GSSAPI_KRB5_INIT (&context);

    memset(&kcred, 0, sizeof(kcred));

    ret = krb5_get_init_creds_opt_alloc(context, &opt);
    if (ret)
	goto out;

    krb5_get_init_creds_opt_set_tkt_life(opt, 300);
    krb5_get_init_creds_opt_set_forwardable(opt, FALSE);
    krb5_get_init_creds_opt_set_proxiable(opt, FALSE);

    ret = krb5_get_init_creds_password(context,
				       &kcred,
				       principal,
				       oldpw,
				       NULL,
				       NULL,
				       0,
				       "kadmin/changepw",
				       opt);
    if (ret)
	goto out;
    
    ret = krb5_set_password(context, &kcred, newpw, NULL,
			    &result_code, &result_code_string, &result_string);
    if (ret)
	goto out;

    krb5_data_free(&result_string);
    krb5_data_free(&result_code_string);

    if (result_code) {
	krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY, 
			       "Failed to change invalid password: %d", result_code);
	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
	goto out;
    }

 out:
    if (opt)
	krb5_get_init_creds_opt_free(context, opt);
    krb5_free_cred_contents(context, &kcred);

    *minor_status = ret;

    return ret ? GSS_S_FAILURE : GSS_S_COMPLETE;
}
示例#2
0
文件: gic_pwd.c 项目: Baalmart/krb5
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_password(krb5_context context,
                             krb5_creds *creds,
                             krb5_principal client,
                             const char *password,
                             krb5_prompter_fct prompter,
                             void *data,
                             krb5_deltat start_time,
                             const char *in_tkt_service,
                             krb5_get_init_creds_opt *options)
{
    krb5_error_code ret, ret2;
    int use_master;
    krb5_kdc_rep *as_reply;
    int tries;
    krb5_creds chpw_creds;
    krb5_get_init_creds_opt *chpw_opts = NULL;
    krb5_data pw0, pw1;
    char banner[1024], pw0array[1024], pw1array[1024];
    krb5_prompt prompt[2];
    krb5_prompt_type prompt_types[sizeof(prompt)/sizeof(prompt[0])];
    char *message;

    use_master = 0;
    as_reply = NULL;
    memset(&chpw_creds, 0, sizeof(chpw_creds));

    pw0.data = pw0array;

    if (password && password[0]) {
        if (strlcpy(pw0.data, password, sizeof(pw0array)) >= sizeof(pw0array)) {
            ret = EINVAL;
            goto cleanup;
        }
        pw0.length = strlen(password);
    } else {
        pw0.data[0] = '\0';
        pw0.length = sizeof(pw0array);
    }

    pw1.data = pw1array;
    pw1.data[0] = '\0';
    pw1.length = sizeof(pw1array);

    /* first try: get the requested tkt from any kdc */

    ret = krb5int_get_init_creds(context, creds, client, prompter, data,
                                 start_time, in_tkt_service, options,
                                 krb5_get_as_key_password, (void *) &pw0,
                                 &use_master, &as_reply);

    /* check for success */

    if (ret == 0)
        goto cleanup;

    /* If all the kdc's are unavailable, or if the error was due to a
       user interrupt, fail */

    if ((ret == KRB5_KDC_UNREACH) ||
        (ret == KRB5_LIBOS_PWDINTR) ||
        (ret == KRB5_REALM_CANT_RESOLVE))
        goto cleanup;

    /* if the reply did not come from the master kdc, try again with
       the master kdc */

    if (!use_master) {
        TRACE_GIC_PWD_MASTER(context);
        use_master = 1;

        if (as_reply) {
            krb5_free_kdc_rep( context, as_reply);
            as_reply = NULL;
        }
        ret2 = krb5int_get_init_creds(context, creds, client, prompter, data,
                                      start_time, in_tkt_service, options,
                                      krb5_get_as_key_password, (void *) &pw0,
                                      &use_master, &as_reply);

        if (ret2 == 0) {
            ret = 0;
            goto cleanup;
        }

        /* if the master is unreachable, return the error from the
           slave we were able to contact or reset the use_master flag */

        if ((ret2 != KRB5_KDC_UNREACH) &&
            (ret2 != KRB5_REALM_CANT_RESOLVE) &&
            (ret2 != KRB5_REALM_UNKNOWN))
            ret = ret2;
        else
            use_master = 0;
    }

    /* at this point, we have an error from the master.  if the error
       is not password expired, or if it is but there's no prompter,
       return this error */

    if ((ret != KRB5KDC_ERR_KEY_EXP) ||
        (prompter == NULL))
        goto cleanup;

    /* historically the default has been to prompt for password change.
     * if the change password prompt option has not been set, we continue
     * to prompt.  Prompting is only disabled if the option has been set
     * and the value has been set to false.
     */
    if (options && !(options->flags & KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT))
        goto cleanup;
    TRACE_GIC_PWD_EXPIRED(context);

    /* ok, we have an expired password.  Give the user a few chances
       to change it */

    /* use a minimal set of options */

    ret = krb5_get_init_creds_opt_alloc(context, &chpw_opts);
    if (ret)
        goto cleanup;
    krb5_get_init_creds_opt_set_tkt_life(chpw_opts, 5*60);
    krb5_get_init_creds_opt_set_renew_life(chpw_opts, 0);
    krb5_get_init_creds_opt_set_forwardable(chpw_opts, 0);
    krb5_get_init_creds_opt_set_proxiable(chpw_opts, 0);

    if ((ret = krb5int_get_init_creds(context, &chpw_creds, client,
                                      prompter, data,
                                      start_time, "kadmin/changepw", chpw_opts,
                                      krb5_get_as_key_password, (void *) &pw0,
                                      &use_master, NULL)))
        goto cleanup;

    prompt[0].prompt = _("Enter new password");
    prompt[0].hidden = 1;
    prompt[0].reply = &pw0;
    prompt_types[0] = KRB5_PROMPT_TYPE_NEW_PASSWORD;

    prompt[1].prompt = _("Enter it again");
    prompt[1].hidden = 1;
    prompt[1].reply = &pw1;
    prompt_types[1] = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN;

    strlcpy(banner, _("Password expired.  You must change it now."),
            sizeof(banner));

    for (tries = 3; tries; tries--) {
        TRACE_GIC_PWD_CHANGEPW(context, tries);
        pw0.length = sizeof(pw0array);
        pw1.length = sizeof(pw1array);

        /* PROMPTER_INVOCATION */
        krb5int_set_prompt_types(context, prompt_types);
        ret = (*prompter)(context, data, 0, banner,
                          sizeof(prompt)/sizeof(prompt[0]), prompt);
        krb5int_set_prompt_types(context, 0);
        if (ret)
            goto cleanup;

        if (strcmp(pw0.data, pw1.data) != 0) {
            ret = KRB5_LIBOS_BADPWDMATCH;
            snprintf(banner, sizeof(banner),
                     _("%s.  Please try again."), error_message(ret));
        } else if (pw0.length == 0) {
            ret = KRB5_CHPW_PWDNULL;
            snprintf(banner, sizeof(banner),
                     _("%s.  Please try again."), error_message(ret));
        } else {
            int result_code;
            krb5_data code_string;
            krb5_data result_string;

            if ((ret = krb5_change_password(context, &chpw_creds, pw0array,
                                            &result_code, &code_string,
                                            &result_string)))
                goto cleanup;

            /* the change succeeded.  go on */

            if (result_code == 0) {
                free(result_string.data);
                break;
            }

            /* set this in case the retry loop falls through */

            ret = KRB5_CHPW_FAIL;

            if (result_code != KRB5_KPASSWD_SOFTERROR) {
                free(result_string.data);
                goto cleanup;
            }

            /* the error was soft, so try again */

            if (krb5_chpw_message(context, &result_string, &message) != 0)
                message = NULL;

            /* 100 is I happen to know that no code_string will be longer
               than 100 chars */

            if (message != NULL && strlen(message) > (sizeof(banner) - 100))
                message[sizeof(banner) - 100] = '\0';

            snprintf(banner, sizeof(banner),
                     _("%.*s%s%s.  Please try again.\n"),
                     (int) code_string.length, code_string.data,
                     message ? ": " : "", message ? message : "");

            free(message);
            free(code_string.data);
            free(result_string.data);
        }
    }

    if (ret)
        goto cleanup;

    /* the password change was successful.  Get an initial ticket
       from the master.  this is the last try.  the return from this
       is final.  */

    TRACE_GIC_PWD_CHANGED(context);
    ret = krb5int_get_init_creds(context, creds, client, prompter, data,
                                 start_time, in_tkt_service, options,
                                 krb5_get_as_key_password, (void *) &pw0,
                                 &use_master, &as_reply);
    if (ret)
        goto cleanup;

cleanup:
    if (ret == 0)
        warn_pw_expiry(context, options, prompter, data, in_tkt_service,
                       as_reply);

    if (chpw_opts)
        krb5_get_init_creds_opt_free(context, chpw_opts);
    memset(pw0array, 0, sizeof(pw0array));
    memset(pw1array, 0, sizeof(pw1array));
    krb5_free_cred_contents(context, &chpw_creds);
    if (as_reply)
        krb5_free_kdc_rep(context, as_reply);

    return(ret);
}
示例#3
0
文件: ad.c 项目: jonrober/krb5-sync
/*
 * Given the plugin options, a Kerberos context, and a pointer to krb5_ccache
 * storage, initialize a memory cache using the configured keytab to obtain
 * initial credentials.  Returns a Kerberos status code.
 */
static krb5_error_code
get_creds(kadm5_hook_modinfo *config, krb5_context ctx, krb5_ccache *cc)
{
    krb5_error_code code;
    krb5_keytab kt = NULL;
    krb5_principal princ = NULL;
    krb5_get_init_creds_opt *opts = NULL;
    krb5_creds creds;
    bool creds_valid = false;
    const char *realm UNUSED;

    /* Initialize the credential cache pointer to NULL. */
    *cc = NULL;

    /* Ensure the configuration is sane. */
    CHECK_CONFIG(ad_keytab);
    CHECK_CONFIG(ad_principal);

    /* Resolve the keytab and principal used to get credentials. */
    code = krb5_kt_resolve(ctx, config->ad_keytab, &kt);
    if (code != 0)
        goto fail;
    code = krb5_parse_name(ctx, config->ad_principal, &princ);
    if (code != 0)
        goto fail;

    /* Set our credential acquisition options. */
    code = krb5_get_init_creds_opt_alloc(ctx, &opts);
    if (code != 0)
        goto fail;
    realm = krb5_principal_get_realm(ctx, princ);
    krb5_get_init_creds_opt_set_default_flags(ctx, "krb5-sync", realm, opts);

    /* Obtain credentials. */
    memset(&creds, 0, sizeof(creds));
    code = krb5_get_init_creds_keytab(ctx, &creds, princ, kt, 0, NULL, opts);
    if (code != 0)
        goto fail;
    krb5_get_init_creds_opt_free(ctx, opts);
    opts = NULL;
    krb5_kt_close(ctx, kt);
    kt = NULL;
    creds_valid = true;

    /* Open and initialize the credential cache. */
    code = krb5_cc_resolve(ctx, CACHE_NAME, cc);
    if (code != 0)
        goto fail;
    code = krb5_cc_initialize(ctx, *cc, princ);
    if (code == 0)
        code = krb5_cc_store_cred(ctx, *cc, &creds);
    if (code != 0) {
        krb5_cc_close(ctx, *cc);
        *cc = NULL;
        goto fail;
    }

    /* Clean up and return success. */
    krb5_free_cred_contents(ctx, &creds);
    krb5_free_principal(ctx, princ);
    return 0;

fail:
    if (kt != NULL)
        krb5_kt_close(ctx, kt);
    if (princ != NULL)
        krb5_free_principal(ctx, princ);
    if (opts != NULL)
        krb5_get_init_creds_opt_free(ctx, opts);
    if (creds_valid)
        krb5_free_cred_contents(ctx, &creds);
    return code;
}
示例#4
0
/* call-seq:
 *   krb5.get_init_creds_keytab(principal = nil, keytab = nil, service = nil, ccache = nil)
 *
 * Acquire credentials for +principal+ from +keytab+ using +service+. If
 * no principal is specified, then a principal is derived from the service
 * name. If no service name is specified, kerberos defaults to "host".
 *
 * If no keytab file is provided, the default keytab file is used. This is
 * typically /etc/krb5.keytab.
 *
 * If +ccache+ is supplied and is a Kerberos::Krb5::CredentialsCache, the
 * resulting credentials will be stored in the credential cache.
 */
static VALUE rkrb5_get_init_creds_keytab(int argc, VALUE* argv, VALUE self){
  RUBY_KRB5* ptr;
  VALUE v_user, v_keytab_name, v_service, v_ccache;
  char* user;
  char* service;
  char keytab_name[MAX_KEYTAB_NAME_LEN];

  krb5_error_code kerror;
  krb5_get_init_creds_opt* opt;
  krb5_creds cred;

  Data_Get_Struct(self, RUBY_KRB5, ptr); 

  if(!ptr->ctx)
    rb_raise(cKrb5Exception, "no context has been established");

  kerror = krb5_get_init_creds_opt_alloc(ptr->ctx, &opt);
  if(kerror)
    rb_raise(cKrb5Exception, "krb5_get_init_creds_opt_alloc: %s", error_message(kerror));

  rb_scan_args(argc, argv, "04", &v_user, &v_keytab_name, &v_service, &v_ccache);

  // We need the service information for later.
  if(NIL_P(v_service)){
    service = NULL;
  }
  else{
    Check_Type(v_service, T_STRING);
    service = StringValuePtr(v_service);
  }

  // Convert the name (or service name) to a kerberos principal.
  if(NIL_P(v_user)){
    kerror = krb5_sname_to_principal(
      ptr->ctx,
      NULL,
      service,
      KRB5_NT_SRV_HST,
      &ptr->princ
    );

    if(kerror) {
      krb5_get_init_creds_opt_free(ptr->ctx, opt);
      rb_raise(cKrb5Exception, "krb5_sname_to_principal: %s", error_message(kerror));
    }
  }
  else{
    Check_Type(v_user, T_STRING);
    user = StringValuePtr(v_user);

    kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ); 

    if(kerror) {
      krb5_get_init_creds_opt_free(ptr->ctx, opt);
      rb_raise(cKrb5Exception, "krb5_parse_name: %s", error_message(kerror));
    }
  }

  // Use the default keytab if none is specified.
  if(NIL_P(v_keytab_name)){
    kerror = krb5_kt_default_name(ptr->ctx, keytab_name, MAX_KEYTAB_NAME_LEN);

    if(kerror) {
      krb5_get_init_creds_opt_free(ptr->ctx, opt);
      rb_raise(cKrb5Exception, "krb5_kt_default_name: %s", error_message(kerror));
    }
  }
  else{
    Check_Type(v_keytab_name, T_STRING);
    strncpy(keytab_name, StringValuePtr(v_keytab_name), MAX_KEYTAB_NAME_LEN);
  }

  kerror = krb5_kt_resolve(
    ptr->ctx,
    keytab_name,
    &ptr->keytab
  );

  if(kerror) {
    krb5_get_init_creds_opt_free(ptr->ctx, opt);
    rb_raise(cKrb5Exception, "krb5_kt_resolve: %s", error_message(kerror));
  }

  // Set the credential cache from the supplied Kerberos::Krb5::CredentialsCache
  if(!NIL_P(v_ccache)){
    RUBY_KRB5_CCACHE* ccptr;
    Data_Get_Struct(v_ccache, RUBY_KRB5_CCACHE, ccptr);

    kerror = krb5_get_init_creds_opt_set_out_ccache(ptr->ctx, opt, ccptr->ccache);
    if(kerror) {
      krb5_get_init_creds_opt_free(ptr->ctx, opt);
      rb_raise(cKrb5Exception, "krb5_get_init_creds_opt_set_out_ccache: %s", error_message(kerror));
    }
  }

  kerror = krb5_get_init_creds_keytab(
    ptr->ctx,
    &cred,
    ptr->princ,
    ptr->keytab,
    0,
    service,
    opt
  );

  if(kerror) {
    krb5_get_init_creds_opt_free(ptr->ctx, opt);
    rb_raise(cKrb5Exception, "krb5_get_init_creds_keytab: %s", error_message(kerror));
  }

  krb5_get_init_creds_opt_free(ptr->ctx, opt);

  return self; 
}
示例#5
0
static krb5_error_code
login_perform_kinit (krb5_context k5,
                     const gchar *realm,
                     const gchar *login,
                     const gchar *password,
                     const gchar *filename)
{
        krb5_get_init_creds_opt *opts;
        krb5_error_code code;
        krb5_principal principal;
        krb5_ccache ccache;
        krb5_creds creds;
        gchar *name;

        name = g_strdup_printf ("%s@%s", login, realm);
        code = krb5_parse_name (k5, name, &principal);

        if (code != 0) {
                g_debug ("Couldn't parse principal name: %s: %s",
                         name, krb5_get_error_message (k5, code));
                g_free (name);
                return code;
        }

        g_debug ("Using principal name to kinit: %s", name);
        g_free (name);

        if (filename == NULL)
                code = krb5_cc_default (k5, &ccache);
        else
                code = krb5_cc_resolve (k5, filename, &ccache);

        if (code != 0) {
                krb5_free_principal (k5, principal);
                g_debug ("Couldn't open credential cache: %s: %s",
                         filename ? filename : "<default>",
                         krb5_get_error_message (k5, code));
                return code;
        }

        code = krb5_get_init_creds_opt_alloc (k5, &opts);
        g_return_val_if_fail (code == 0, code);

        code = krb5_get_init_creds_opt_set_out_ccache (k5, opts, ccache);
        g_return_val_if_fail (code == 0, code);

        code = krb5_get_init_creds_password (k5, &creds, principal,
                                             (char *)password,
                                             NULL, 0, 0, NULL, opts);

        krb5_get_init_creds_opt_free (k5, opts);
        krb5_cc_close (k5, ccache);
        krb5_free_principal (k5, principal);

        if (code == 0) {
                g_debug ("kinit succeeded");
                krb5_free_cred_contents (k5, &creds);
        } else {
                g_debug ("kinit failed: %s", krb5_get_error_message (k5, code));
        }

        return code;
}
示例#6
0
文件: kinit.c 项目: lha/heimdal
static krb5_error_code
get_new_tickets(krb5_context context,
		krb5_principal principal,
		krb5_ccache ccache,
		krb5_deltat ticket_life,
		int interactive)
{
    krb5_error_code ret;
    krb5_get_init_creds_opt *opt;
    krb5_creds cred;
    char passwd[256];
    krb5_deltat start_time = 0;
    krb5_deltat renew = 0;
    const char *renewstr = NULL;
    krb5_enctype *enctype = NULL;
    krb5_ccache tempccache;
    krb5_keytab kt = NULL;
    krb5_init_creds_context ctx;
#ifndef NO_NTLM
    struct ntlm_buf ntlmkey;
    memset(&ntlmkey, 0, sizeof(ntlmkey));
#endif
    passwd[0] = '\0';

    if (password_file) {
	FILE *f;

	if (strcasecmp("STDIN", password_file) == 0)
	    f = stdin;
	else
	    f = fopen(password_file, "r");
	if (f == NULL)
	    krb5_errx(context, 1, "Failed to open the password file %s",
		      password_file);

	if (fgets(passwd, sizeof(passwd), f) == NULL)
	    krb5_errx(context, 1,
		      N_("Failed to read password from file %s", ""),
		      password_file);
	if (f != stdin)
	    fclose(f);
	passwd[strcspn(passwd, "\n")] = '\0';
    }

#ifdef __APPLE__
    if (passwd[0] == '\0') {
	const char *realm;
	OSStatus osret;
	UInt32 length;
	void *buffer;
	char *name;

	realm = krb5_principal_get_realm(context, principal);

	ret = krb5_unparse_name_flags(context, principal,
				      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
	if (ret)
	    goto nopassword;

	osret = SecKeychainFindGenericPassword(NULL, strlen(realm), realm,
					       strlen(name), name,
					       &length, &buffer, NULL);
	free(name);
	if (osret == noErr && length < sizeof(passwd) - 1) {
	    memcpy(passwd, buffer, length);
	    passwd[length] = '\0';
	}
    nopassword:
	do { } while(0);
    }
#endif

    memset(&cred, 0, sizeof(cred));

    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_default_flags(context, "kinit",
	krb5_principal_get_realm(context, principal), opt);

    if(forwardable_flag != -1)
	krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag);
    if(proxiable_flag != -1)
	krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag);
    if(anonymous_flag)
	krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag);
    if (pac_flag != -1)
	krb5_get_init_creds_opt_set_pac_request(context, opt,
						pac_flag ? TRUE : FALSE);
    if (canonicalize_flag)
	krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
    if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag)
	krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
    if (pk_user_id || ent_user_id || anonymous_flag) {
	ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
						 principal,
						 pk_user_id,
						 pk_x509_anchors,
						 NULL,
						 NULL,
						 pk_use_enckey ? 2 : 0 |
						 anonymous_flag ? 4 : 0,
						 krb5_prompter_posix,
						 NULL,
						 passwd);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
	if (ent_user_id)
	    krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id);
    }

    if (addrs_flag != -1)
	krb5_get_init_creds_opt_set_addressless(context, opt,
						addrs_flag ? FALSE : TRUE);

    if (renew_life == NULL && renewable_flag)
	renewstr = "1 month";
    if (renew_life)
	renewstr = renew_life;
    if (renewstr) {
	renew = parse_time (renewstr, "s");
	if (renew < 0)
	    errx (1, "unparsable time: %s", renewstr);

	krb5_get_init_creds_opt_set_renew_life (opt, renew);
    }

    if(ticket_life != 0)
	krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life);

    if(start_str) {
	int tmp = parse_time (start_str, "s");
	if (tmp < 0)
	    errx (1, N_("unparsable time: %s", ""), start_str);

	start_time = tmp;
    }

    if(etype_str.num_strings) {
	int i;

	enctype = malloc(etype_str.num_strings * sizeof(*enctype));
	if(enctype == NULL)
	    errx(1, "out of memory");
	for(i = 0; i < etype_str.num_strings; i++) {
	    ret = krb5_string_to_enctype(context,
					 etype_str.strings[i],
					 &enctype[i]);
	    if(ret)
		errx(1, "unrecognized enctype: %s", etype_str.strings[i]);
	}
	krb5_get_init_creds_opt_set_etype_list(opt, enctype,
					       etype_str.num_strings);
    }

    ret = krb5_init_creds_init(context, principal, krb5_prompter_posix, NULL, start_time, opt, &ctx);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_init");

    if (server_str) {
	ret = krb5_init_creds_set_service(context, ctx, server_str);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_service");
    }

    if (fast_armor_cache_string) {
	krb5_ccache fastid;
	
	ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve(FAST cache)");
	
	ret = krb5_init_creds_set_fast_ccache(context, ctx, fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_fast_ccache");
    }

    if(use_keytab || keytab_str) {

	if(keytab_str)
	    ret = krb5_kt_resolve(context, keytab_str, &kt);
	else
	    ret = krb5_kt_default(context, &kt);
	if (ret)
	    krb5_err(context, 1, ret, "resolving keytab");

	ret = krb5_init_creds_set_keytab(context, ctx, kt);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_keytab");

    } else if (pk_user_id || ent_user_id || anonymous_flag) {

    } else if (!interactive) {
	krb5_warnx(context, "Not interactive, failed to get initial ticket");
	krb5_get_init_creds_opt_free(context, opt);
	return 0;
    } else {

	if (passwd[0] == '\0') {
	    char *p, *prompt;

	    krb5_unparse_name (context, principal, &p);
	    asprintf (&prompt, N_("%s's Password: "******""), p);
	    free (p);

	    if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
		memset(passwd, 0, sizeof(passwd));
		errx(1, "failed to read password");
	    }
	    free (prompt);
	}

	if (passwd[0]) {
	    ret = krb5_init_creds_set_password(context, ctx, passwd);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_init_creds_set_password");
	}
    }

    ret = krb5_init_creds_get(context, ctx);

#ifndef NO_NTLM
    if (ntlm_domain && passwd[0])
	heim_ntlm_nt_key(passwd, &ntlmkey);
#endif
    memset(passwd, 0, sizeof(passwd));

    switch(ret){
    case 0:
	break;
    case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */
	exit(1);
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KRB_AP_ERR_MODIFIED:
    case KRB5KDC_ERR_PREAUTH_FAILED:
	krb5_errx(context, 1, N_("Password incorrect", ""));
	break;
    case KRB5KRB_AP_ERR_V4_REPLY:
	krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", ""));
	break;
    default:
	krb5_err(context, 1, ret, "krb5_get_init_creds");
    }

    krb5_process_last_request(context, opt, ctx);

    if(ticket_life != 0) {
	if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) {
	    char life[64];
	    unparse_time_approx(cred.times.endtime - cred.times.starttime,
				life, sizeof(life));
	    krb5_warnx(context, N_("NOTICE: ticket lifetime is %s", ""), life);
	}
    }
    if(renew_life) {
	if(abs(cred.times.renew_till - cred.times.starttime - renew) > 30) {
	    char life[64];
	    unparse_time_approx(cred.times.renew_till - cred.times.starttime,
				life, sizeof(life));
	    krb5_warnx(context,
		       N_("NOTICE: ticket renewable lifetime is %s", ""),
		       life);
	}
    }

    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache),
			     NULL, &tempccache);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_new_unique");

    ret = krb5_init_creds_store(context, ctx, tempccache);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_store");

    krb5_init_creds_free(context, ctx);

    ret = krb5_cc_move(context, tempccache, ccache);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_move");

    if (switch_cache_flags)
	krb5_cc_switch(context, ccache);

#ifndef NO_NTLM
    if (ntlm_domain && ntlmkey.data)
	store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey);
#endif

    if (ok_as_delegate_flag || windows_flag || use_referrals_flag) {
	unsigned char d = 0;
	krb5_data data;

	if (ok_as_delegate_flag || windows_flag)
	    d |= 1;
	if (use_referrals_flag || windows_flag)
	    d |= 2;

	data.length = 1;
	data.data = &d;

	krb5_cc_set_config(context, ccache, NULL, "realm-config", &data);
    }

    krb5_get_init_creds_opt_free(context, opt);

    if (kt)			
	krb5_kt_close(context, kt);
    if (enctype)
	free(enctype);

    return 0;
}
示例#7
0
static OM_uint32 acquire_initiator_cred
		  (OM_uint32 * minor_status,
		   krb5_context context,
		   gss_const_OID credential_type,
		   const void *credential_data,
		   gss_const_name_t desired_name,
		   OM_uint32 time_req,
		   gss_const_OID desired_mech,
		   gss_cred_usage_t cred_usage,
		   gsskrb5_cred handle
		  )
{
    OM_uint32 ret;
    krb5_creds cred;
    krb5_principal def_princ;
    krb5_get_init_creds_opt *opt;
    krb5_ccache ccache;
    krb5_keytab keytab;
    krb5_error_code kret;

    keytab = NULL;
    ccache = NULL;
    def_princ = NULL;
    ret = GSS_S_FAILURE;
    memset(&cred, 0, sizeof(cred));

    /*
     * If we have a preferred principal, lets try to find it in all
     * caches, otherwise, fall back to default cache, ignore all
     * errors while searching.
     */

    if (credential_type != GSS_C_NO_OID &&
	!gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) {
	kret = KRB5_NOCREDS_SUPPLIED; /* XXX */
	goto end;
    }

    if (handle->principal) {
	kret = krb5_cc_cache_match (context,
				    handle->principal,
				    &ccache);
	if (kret == 0) {
	    ret = GSS_S_COMPLETE;
	    goto found;
	}
    }

    if (ccache == NULL) {
	kret = krb5_cc_default(context, &ccache);
	if (kret)
	    goto end;
    }
    kret = krb5_cc_get_principal(context, ccache, &def_princ);
    if (kret != 0) {
	/* we'll try to use a keytab below */
	krb5_cc_close(context, ccache);
	def_princ = NULL;
	kret = 0;
    } else if (handle->principal == NULL)  {
	kret = krb5_copy_principal(context, def_princ, &handle->principal);
	if (kret)
	    goto end;
    } else if (handle->principal != NULL &&
	       krb5_principal_compare(context, handle->principal,
				      def_princ) == FALSE) {
	krb5_free_principal(context, def_princ);
	def_princ = NULL;
	krb5_cc_close(context, ccache);
	ccache = NULL;
    }
    if (def_princ == NULL) {
	/* We have no existing credentials cache,
	 * so attempt to get a TGT using a keytab.
	 */
	if (handle->principal == NULL) {
	    kret = krb5_get_default_principal(context, &handle->principal);
	    if (kret)
		goto end;
	}
	kret = krb5_get_init_creds_opt_alloc(context, &opt);
	if (kret)
	    goto end;
	if (credential_type != GSS_C_NO_OID &&
	    gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) {
	    gss_buffer_t password = (gss_buffer_t)credential_data;

	    /* XXX are we requiring password to be NUL terminated? */

	    kret = krb5_get_init_creds_password(context, &cred,
						handle->principal,
						password->value,
						NULL, NULL, 0, NULL, opt);
	} else {
	    kret = get_keytab(context, &keytab);
	    if (kret) {
		krb5_get_init_creds_opt_free(context, opt);
		goto end;
	    }
	    kret = krb5_get_init_creds_keytab(context, &cred,
					      handle->principal, keytab,
					      0, NULL, opt);
	}
	krb5_get_init_creds_opt_free(context, opt);
	if (kret)
	    goto end;
	kret = krb5_cc_new_unique(context, krb5_cc_type_memory,
				  NULL, &ccache);
	if (kret)
	    goto end;
	kret = krb5_cc_initialize(context, ccache, cred.client);
	if (kret) {
	    krb5_cc_destroy(context, ccache);
	    goto end;
	}
	kret = krb5_cc_store_cred(context, ccache, &cred);
	if (kret) {
	    krb5_cc_destroy(context, ccache);
	    goto end;
	}
	handle->lifetime = cred.times.endtime;
	handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
    } else {

	ret = __gsskrb5_ccache_lifetime(minor_status,
					context,
					ccache,
					handle->principal,
					&handle->lifetime);
	if (ret != GSS_S_COMPLETE) {
	    krb5_cc_close(context, ccache);
	    goto end;
	}
	kret = 0;
    }
 found:
    handle->ccache = ccache;
    ret = GSS_S_COMPLETE;

end:
    if (cred.client != NULL)
	krb5_free_cred_contents(context, &cred);
    if (def_princ != NULL)
	krb5_free_principal(context, def_princ);
    if (keytab != NULL)
	krb5_kt_close(context, keytab);
    if (ret != GSS_S_COMPLETE && kret != 0)
	*minor_status = kret;
    return (ret);
}
示例#8
0
    ngx_int_t
ngx_http_auth_spnego_basic(
        ngx_http_request_t * r,
        ngx_http_auth_spnego_ctx_t * ctx,
        ngx_http_auth_spnego_loc_conf_t * alcf)
{
    ngx_str_t host_name;
    ngx_str_t service;
    ngx_str_t user;
    user.data = NULL;
    ngx_str_t new_user;
    ngx_int_t ret = NGX_DECLINED;

    krb5_context kcontext = NULL;
    krb5_error_code code;
    krb5_principal client = NULL;
    krb5_principal server = NULL;
    krb5_creds creds;
    krb5_get_init_creds_opt *gic_options = NULL;
    int kret = 0;
    char *name = NULL;
    char *p = NULL;

    code = krb5_init_context(&kcontext);
    if (code) {
        spnego_debug0("Kerberos error: Cannot initialize kerberos context");
        return NGX_ERROR;
    }

    host_name = r->headers_in.host->value;
    service.len = alcf->srvcname.len + alcf->realm.len + 3;

    if (ngx_strchr(alcf->srvcname.data, '/')) {
        service.data = ngx_palloc(r->pool, service.len);
        if (NULL == service.data) {
            spnego_error(NGX_ERROR);
        }

        ngx_snprintf(service.data, service.len, "%V@%V%Z",
                &alcf->srvcname, &alcf->realm);
    } else {
        service.len += host_name.len;
        service.data = ngx_palloc(r->pool, service.len);
        if (NULL == service.data) {
            spnego_error(NGX_ERROR);
        }

        ngx_snprintf(service.data, service.len, "%V/%V@%V%Z",
                &alcf->srvcname, &host_name, &alcf->realm);
    }

    kret = krb5_parse_name(kcontext, (const char *) service.data, &server);

    if (kret) {
        spnego_log_error("Kerberos error:  Unable to parse service name");
        spnego_log_krb5_error(kcontext, code);
        spnego_error(NGX_ERROR);
    }

    code = krb5_unparse_name(kcontext, server, &name);
    if (code) {
        spnego_log_error("Kerberos error: Cannot unparse servicename");
        spnego_log_krb5_error(kcontext, code);
        spnego_error(NGX_ERROR);
    }

    free(name);
    name = NULL;

    p = ngx_strchr(r->headers_in.user.data, '@');
    user.len = r->headers_in.user.len + 1;
    if (NULL == p) {
        if (alcf->force_realm && alcf->realm.len && alcf->realm.data ) {
            user.len += alcf->realm.len + 1; /* +1 for @ */
            user.data = ngx_palloc(r->pool, user.len);
            if (NULL == user.data) {
                spnego_log_error("Not enough memory");
                spnego_error(NGX_ERROR);
            }
            ngx_snprintf(user.data, user.len, "%V@%V%Z", &r->headers_in.user,
                    &alcf->realm);
        } else {
            user.data = ngx_palloc(r->pool, user.len);
            if (NULL == user.data) {
                spnego_log_error("Not enough memory");
                spnego_error(NGX_ERROR);
            }
            ngx_snprintf(user.data, user.len, "%V%Z", &r->headers_in.user);
        }
    } else {
        if (alcf->realm.len && alcf->realm.data && ngx_strncmp(p + 1,
                    alcf->realm.data, alcf->realm.len) == 0) {
            user.data = ngx_palloc(r->pool, user.len);
            if (NULL == user.data) {
                spnego_log_error("Not enough memory");
                spnego_error(NGX_ERROR);
            }
            ngx_snprintf(user.data, user.len, "%V%Z",
                    &r->headers_in.user);
            if (alcf->fqun == 0) {
                /*
                 * Specified realm is identical to configured realm.
                 * Truncate $remote_user to strip @REALM.
                 */
                r->headers_in.user.len -= alcf->realm.len + 1;
            }
        } else if (alcf->force_realm) {
            *p = '\0';
            user.len = ngx_strlen(r->headers_in.user.data) + 1;
            if (alcf->realm.len && alcf->realm.data)
                user.len += alcf->realm.len + 1;
            user.data = ngx_pcalloc(r->pool, user.len);
            if (NULL == user.data) {
                spnego_log_error("Not enough memory");
                spnego_error(NGX_ERROR);
            }
            if (alcf->realm.len && alcf->realm.data)
                ngx_snprintf(user.data, user.len, "%s@%V%Z",
                        r->headers_in.user.data, &alcf->realm);
            else
                ngx_snprintf(user.data, user.len, "%s%Z",
                        r->headers_in.user.data);
            /*
             * Rewrite $remote_user with the forced realm.
             * If the forced realm is shorter than the
             * specified realm, we can reuse the original
             * buffer.
             */
            if (r->headers_in.user.len >= user.len - 1)
                r->headers_in.user.len = user.len - 1;
            else {
                new_user.len = user.len - 1;
                new_user.data = ngx_palloc(r->pool, new_user.len);
                if (NULL == new_user.data) {
                    spnego_log_error("Not enough memory");
                    spnego_error(NGX_ERROR);
                }
                ngx_pfree(r->pool, r->headers_in.user.data);
                r->headers_in.user.data = new_user.data;
                r->headers_in.user.len = new_user.len;
            }
            ngx_memcpy(r->headers_in.user.data, user.data,
                    r->headers_in.user.len);
        } else {
            user.data = ngx_palloc(r->pool, user.len);
            if (NULL == user.data) {
                spnego_log_error("Not enough memory");
                spnego_error(NGX_ERROR);
            }
            ngx_snprintf(user.data, user.len, "%V%Z", &r->headers_in.user);
        }
    }

    spnego_debug1("Attempting authentication with principal %s",
            (const char *)user.data);

    code = krb5_parse_name(kcontext, (const char *) user.data, &client);
    if (code) {
        spnego_log_error("Kerberos error: Unable to parse username");
        spnego_debug1("username is %s.", (const char *) user.data);
        spnego_log_krb5_error(kcontext, code);
        spnego_error(NGX_ERROR);
    }

    memset(&creds, 0, sizeof(creds));

    code = krb5_unparse_name(kcontext, client, &name);
    if (code) {
        spnego_log_error("Kerberos error: Cannot unparse username");
        spnego_log_krb5_error(kcontext, code);
        spnego_error(NGX_ERROR);
    }

    krb5_get_init_creds_opt_alloc(kcontext, &gic_options);

    code = krb5_get_init_creds_password(kcontext, &creds, client,
                (char *) r->headers_in.passwd.data,
                NULL, NULL, 0, NULL, gic_options);

    krb5_free_cred_contents(kcontext, &creds);

    if (code) {
        spnego_log_error("Kerberos error: Credentials failed");
        spnego_log_krb5_error(kcontext, code);
        spnego_error(NGX_DECLINED);
    }

    /* Try to add the system realm to $remote_user if needed. */
    if (alcf->fqun && !ngx_strchr(r->headers_in.user.data, '@')) {
#ifdef krb5_princ_realm
        /*
         * MIT does not have krb5_principal_get_realm() but its
         * krb5_princ_realm() is a macro that effectively points
         * to a char *.
         */
        const char *realm = krb5_princ_realm(kcontext, client)->data;
#else
        const char *realm = krb5_principal_get_realm(kcontext, client);
#endif
        if (realm) {
            new_user.len = r->headers_in.user.len + 1 + ngx_strlen(realm);
            new_user.data = ngx_palloc(r->pool, new_user.len);
            if (NULL == new_user.data) {
                spnego_log_error("Not enough memory");
                spnego_error(NGX_ERROR);
            }
            ngx_snprintf(new_user.data, new_user.len, "%V@%s",
                    &r->headers_in.user, realm);
            ngx_pfree(r->pool, r->headers_in.user.data);
            r->headers_in.user.data = new_user.data;
            r->headers_in.user.len = new_user.len;
        }
    }

    spnego_debug1("Setting $remote_user to %V", &r->headers_in.user);
    if (ngx_http_auth_spnego_set_bogus_authorization(r) != NGX_OK)
        spnego_log_error("Failed to set $remote_user");

    spnego_debug0("ngx_http_auth_spnego_basic: returning NGX_OK");

    ret = NGX_OK;

end:
    if (name)
        free(name);
    if (client)
        krb5_free_principal(kcontext, client);
    if (server)
        krb5_free_principal(kcontext, server);
    if (service.data)
        ngx_pfree(r->pool, service.data);
    if (user.data)
        ngx_pfree(r->pool, user.data);

    krb5_get_init_creds_opt_free(kcontext, gic_options);

    krb5_free_context(kcontext);

    return ret;
}
示例#9
0
文件: kinit.c 项目: aosm/Heimdal
static krb5_error_code
get_new_tickets(krb5_context context,
		krb5_principal principal,
		krb5_ccache ccache,
		krb5_deltat ticket_life,
		int interactive)
{
    krb5_error_code ret;
    krb5_get_init_creds_opt *opt;
    krb5_creds cred;
    char passwd[256];
    krb5_deltat start_time = 0;
    krb5_deltat renew = 0;
    const char *renewstr = NULL;
    krb5_enctype *enctype = NULL;
    krb5_ccache tempccache;
    krb5_init_creds_context icc;
    krb5_keytab kt = NULL;
    int will_use_keytab =  (use_keytab || keytab_str);
    krb5_prompter_fct prompter = NULL;
    int need_prompt;

    passwd[0] = '\0';

    if (password_file) {
	FILE *f;

	if (strcasecmp("STDIN", password_file) == 0)
	    f = stdin;
	else
	    f = fopen(password_file, "r");
	if (f == NULL)
	    krb5_errx(context, 1, "Failed to open the password file %s",
		      password_file);

	if (fgets(passwd, sizeof(passwd), f) == NULL)
	    krb5_errx(context, 1,
		      N_("Failed to read password from file %s", ""),
		      password_file);
	if (f != stdin)
	    fclose(f);
	passwd[strcspn(passwd, "\n")] = '\0';
    }

#if defined(__APPLE__) && !defined(__APPLE_TARGET_EMBEDDED__)
    if (passwd[0] == '\0' && !will_use_keytab && home_directory_flag) {
	const char *realm;
	OSStatus osret;
	UInt32 length;
	void *buffer;
	char *name;

	realm = krb5_principal_get_realm(context, principal);

	ret = krb5_unparse_name_flags(context, principal,
				      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
	if (ret)
	    goto nopassword;

	osret = SecKeychainFindGenericPassword(NULL, (UInt32)strlen(realm), realm,
					       (UInt32)strlen(name), name,
					       &length, &buffer, &passwordItem);
	free(name);
	if (osret != noErr)
	    goto nopassword;

	if (length < sizeof(passwd) - 1) {
	    memcpy(passwd, buffer, length);
	    passwd[length] = '\0';
	}
	SecKeychainItemFreeContent(NULL, buffer);
    nopassword:
	do { } while(0);
    }
#endif

    need_prompt = !(pk_user_id || ent_user_id || anonymous_flag || will_use_keytab || passwd[0] != '\0') && interactive;
    if (need_prompt)
	prompter = krb5_prompter_posix;
    else
	prompter = krb5_prompter_print_only;

    memset(&cred, 0, sizeof(cred));

    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_default_flags(context, "kinit",
	krb5_principal_get_realm(context, principal), opt);

    if(forwardable_flag != -1)
	krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag);

    if(proxiable_flag != -1)
	krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag);
    if(anonymous_flag)
	krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag);
    if (pac_flag != -1)
	krb5_get_init_creds_opt_set_pac_request(context, opt,
						pac_flag ? TRUE : FALSE);
    if (canonicalize_flag)
	krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
    if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag)
	krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
    if (pk_user_id || ent_user_id || anonymous_flag) {
	ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
						 principal,
						 pk_user_id,
						 pk_x509_anchors,
						 NULL,
						 NULL,
						 pk_use_enckey ? 2 : 0 |
						 anonymous_flag ? 4 : 0,
						 interactive ? krb5_prompter_posix : krb5_prompter_print_only,
						 NULL,
						 passwd);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
	if (ent_user_id)
	    krb5_get_init_creds_opt_set_pkinit_user_cert(context, opt, ent_user_id);
    }

    if (addrs_flag != -1)
	krb5_get_init_creds_opt_set_addressless(context, opt,
						addrs_flag ? FALSE : TRUE);

    if (renew_life == NULL && renewable_flag)
	renewstr = "1 month";
    if (renew_life)
	renewstr = renew_life;
    if (renewstr) {
	renew = parse_time (renewstr, "s");
	if (renew < 0)
	    errx (1, "unparsable time: %s", renewstr);

	krb5_get_init_creds_opt_set_renew_life (opt, renew);
    }

    if(ticket_life != 0)
	krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life);

    if(start_str) {
	int tmp = parse_time (start_str, "s");
	if (tmp < 0)
	    errx (1, N_("unparsable time: %s", ""), start_str);

	start_time = tmp;
    }

    if(etype_str.num_strings) {
	int i;

	enctype = malloc(etype_str.num_strings * sizeof(*enctype));
	if(enctype == NULL)
	    errx(1, "out of memory");
	for(i = 0; i < etype_str.num_strings; i++) {
	    ret = krb5_string_to_enctype(context,
					 etype_str.strings[i],
					 &enctype[i]);
	    if(ret)
		krb5_err(context, 1, ret, "unrecognized enctype: %s",
			 etype_str.strings[i]);
	}
	krb5_get_init_creds_opt_set_etype_list(opt, enctype,
					       etype_str.num_strings);
    }

    ret = krb5_init_creds_init(context, principal,
			       prompter, NULL,
			       start_time, opt, &icc);
    if (ret)
	krb5_err (context, 1, ret, "krb5_init_creds_init");

    if (server_str) {
	ret = krb5_init_creds_set_service(context, icc, server_str);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_init_creds_set_service");
    }

    if (kdc_hostname)
	krb5_init_creds_set_kdc_hostname(context, icc, kdc_hostname);

    if (fast_armor_cache_string) {
	krb5_ccache fastid;
	
	ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve(FAST cache)");
	
	ret = krb5_init_creds_set_fast_ccache(context, icc, fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_fast_ccache");
    }

    if(will_use_keytab) {
	if(keytab_str)
	    ret = krb5_kt_resolve(context, keytab_str, &kt);
	else
	    ret = krb5_kt_default(context, &kt);
	if (ret)
	    krb5_err (context, 1, ret, "resolving keytab");

	ret = krb5_init_creds_set_keytab(context, icc, kt);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_init_creds_set_keytab");
    }

    if (passwd[0] == '\0' && need_prompt) {
	char *p, *prompt;

	krb5_unparse_name(context, principal, &p);
	asprintf (&prompt, N_("%s's Password: "******""), p);
	free(p);

	if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
	    memset(passwd, 0, sizeof(passwd));
	    errx(1, "failed to read password");
	}
	free (prompt);
    }

    if (passwd[0]) {
	ret = krb5_init_creds_set_password(context, icc, passwd);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_password");
    }

    ret = krb5_init_creds_get(context, icc);

#ifdef __APPLE__
    /*
     * Save password in Keychain
     */
    if (ret == 0 && keychain_flag && passwordItem == NULL) {
	krb5_error_code ret2;
	const char *realm;
	char *name;

	realm = krb5_principal_get_realm(context, principal);
	ret2 = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
	if (ret2 == 0) {
	    (void)SecKeychainAddGenericPassword(NULL,
						(UInt32)strlen(realm), realm,
						(UInt32)strlen(name), name,
						(UInt32)strlen(passwd), passwd,
						NULL);
	    free(name);
	}
    }
#endif

    memset(passwd, 0, sizeof(passwd));

    switch(ret){
    case 0:
	break;
    case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */
	exit(1);
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KRB_AP_ERR_MODIFIED:
    case KRB5KDC_ERR_PREAUTH_FAILED:
    case KRB5_GET_IN_TKT_LOOP:
#ifdef __APPLE__
	if (passwordItem)
	    SecKeychainItemDelete(passwordItem);
#endif
	krb5_errx(context, 1, N_("Password incorrect", ""));
    case KRB5KRB_AP_ERR_V4_REPLY:
	krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", ""));
    case KRB5KDC_ERR_KEY_EXPIRED:
	krb5_errx(context, 1, N_("Password expired", ""));
    default:
	krb5_err(context, 1, ret, "krb5_get_init_creds");
    }

    ret = krb5_init_creds_get_creds(context, icc, &cred);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_get_creds");

    krb5_process_last_request(context, opt, icc);

    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache),
			     NULL, &tempccache);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_new_unique");

    ret = krb5_init_creds_store(context, icc, tempccache);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_store");

    ret = krb5_init_creds_store_config(context, icc, tempccache);
    if (ret)
	krb5_warn(context, ret, "krb5_init_creds_store_config");

    ret = krb5_init_creds_warn_user(context, icc);
    if (ret)
	krb5_warn(context, ret, "krb5_init_creds_warn_user");

#ifdef __APPLE__
    /*
     * Set for this case, default to * so that all processes can use
     * this cache.
     */
    {
	heim_array_t bundleacl = heim_array_create();
	heim_string_t ace;

	if (bundle_acl_strings.num_strings > 0) {
	    int i;
	    for (i = 0; i < bundle_acl_strings.num_strings; i++) {
		ace = heim_string_create(bundle_acl_strings.strings[i]);
		heim_array_append_value(bundleacl, ace);
		heim_release(ace);
	    }
	} else {
	    ace = heim_string_create("*");
	    heim_array_append_value(bundleacl, ace);
	    heim_release(ace);
	}
	krb5_cc_set_acl(context, tempccache, "kHEIMAttrBundleIdentifierACL", bundleacl);
	heim_release(bundleacl);
    }
#endif

    ret = krb5_cc_move(context, tempccache, ccache);
    if (ret) {
	(void)krb5_cc_destroy(context, tempccache);
	krb5_err (context, 1, ret, "krb5_cc_move");
    }

    if (switch_cache_flags)
	krb5_cc_switch(context, ccache);

    if (ok_as_delegate_flag || windows_flag || use_referrals_flag) {
	unsigned char d = 0;
	krb5_data data;

	if (ok_as_delegate_flag || windows_flag)
	    d |= 1;
	if (use_referrals_flag || windows_flag)
	    d |= 2;

	data.length = 1;
	data.data = &d;

	krb5_cc_set_config(context, ccache, NULL, "realm-config", &data);
    }

    if (enctype)
	free(enctype);

    krb5_init_creds_free(context, icc);
    krb5_get_init_creds_opt_free(context, opt);

    if (kt)
	krb5_kt_close(context, kt);

#ifdef __APPLE__
    if (passwordItem)
	CFRelease(passwordItem);
#endif

    return 0;
}
示例#10
0
/* Perform one iteration of attempting to get credentials.  This includes
 * searching existing ccache for requested service if INIT_CREDS. */
static kadm5_ret_t
gic_iter(kadm5_server_handle_t handle, enum init_type init_type,
         krb5_ccache ccache, krb5_principal client, char *pass, char *svcname,
         char *realm, krb5_principal *server_out)
{
    kadm5_ret_t code;
    krb5_context ctx;
    krb5_keytab kt;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_creds mcreds, outcreds;

    *server_out = NULL;
    ctx = handle->context;
    kt = NULL;
    memset(&opt, 0, sizeof(opt));
    memset(&mcreds, 0, sizeof(mcreds));
    memset(&outcreds, 0, sizeof(outcreds));

    /* Credentials for kadmin don't need to be forwardable or proxiable. */
    if (init_type != INIT_CREDS) {
        code = krb5_get_init_creds_opt_alloc(ctx, &opt);
        krb5_get_init_creds_opt_set_forwardable(opt, 0);
        krb5_get_init_creds_opt_set_proxiable(opt, 0);
        krb5_get_init_creds_opt_set_out_ccache(ctx, opt, ccache);
        if (init_type == INIT_ANONYMOUS)
            krb5_get_init_creds_opt_set_anonymous(opt, 1);
    }

    if (init_type == INIT_PASS || init_type == INIT_ANONYMOUS) {
        code = krb5_get_init_creds_password(ctx, &outcreds, client, pass,
                                            krb5_prompter_posix,
                                            NULL, 0, svcname, opt);
        if (code)
            goto error;
    } else if (init_type == INIT_SKEY) {
        if (pass) {
            code = krb5_kt_resolve(ctx, pass, &kt);
            if (code)
                goto error;
        }
        code = krb5_get_init_creds_keytab(ctx, &outcreds, client, kt,
                                          0, svcname, opt);
        if (pass)
            krb5_kt_close(ctx, kt);
        if (code)
            goto error;
    } else if (init_type == INIT_CREDS) {
        mcreds.client = client;
        code = krb5_parse_name_flags(ctx, svcname,
                                     KRB5_PRINCIPAL_PARSE_IGNORE_REALM,
                                     &mcreds.server);
        if (code)
            goto error;
        code = krb5_set_principal_realm(ctx, mcreds.server, realm);
        if (code)
            goto error;
        code = krb5_cc_retrieve_cred(ctx, ccache, 0,
                                     &mcreds, &outcreds);
        krb5_free_principal(ctx, mcreds.server);
        if (code)
            goto error;
    } else {
        code = EINVAL;
        goto error;
    }

    /* Steal the server principal of the creds we acquired and return it to the
     * caller, which needs to knows what service to authenticate to. */
    *server_out = outcreds.server;
    outcreds.server = NULL;

error:
    krb5_free_cred_contents(ctx, &outcreds);
    if (opt)
        krb5_get_init_creds_opt_free(ctx, opt);
    return code;
}
示例#11
0
/*
 * VmDirLoginUser Creates a TGT cache for the Process to
 * communicate with the VmDir
*/
DWORD
VmDirKrb5LoginUser(
    PCSTR pszUserName,
    PCSTR pszPassword,
    PCSTR pszKrb5ConfPath /* Optional */
)
{
    DWORD dwError = 0;
    krb5_context context = NULL;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_principal principal = NULL;
    krb5_ccache ccache = NULL;
    krb5_creds creds = { 0 };
    PSTR pszCacheName = NULL;

    if (!IsNullOrEmptyString(pszKrb5ConfPath))
    {
        setenv(KRB5_CONF_PATH, pszKrb5ConfPath, 1);
    }

    dwError = VmDirMapKrbError(
                  krb5_init_context(&context)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirMapKrbError(
                  krb5_get_init_creds_opt_alloc(context, &opt)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    krb5_get_init_creds_opt_set_tkt_life(opt, 8 * 60 * 60); //8 hours ticket
    krb5_get_init_creds_opt_set_forwardable(opt, 1);

    // Creates a File based Credential cache based on defaults
    dwError = VmDirMapKrbError(
                  krb5_cc_new_unique(
                      context,
                      "FILE",
                      "hint",
                      &ccache)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    // it is assumed that pszUserName is in user@REALM format.
    dwError = VmDirMapKrbError(
                  krb5_parse_name(context, pszUserName, &principal)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Let us get the Creds from the Kerberos Server
    dwError =  VmDirMapKrbError(
                   krb5_get_init_creds_password(
                       context,
                       &creds,
                       principal,
                       (PSTR) pszPassword,
                       NULL,
                       NULL,
                       0,
                       NULL,
                       opt)
               );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirMapKrbError(
                  krb5_cc_initialize(context, ccache, principal)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirMapKrbError(
                  krb5_cc_store_cred(context, ccache, &creds)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    pszCacheName = (PSTR)krb5_cc_get_name(context, ccache);
    if ( pszCacheName == NULL)
    {
        dwError = ERROR_NO_CRED_CACHE_NAME;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    // let us set the Value to the Env. Variable so GSSAPI can find it.
    setenv(KRB5_CC_NAME, pszCacheName, 1);

    krb5_cc_set_default_name(context, pszCacheName);

error:

    if (principal != NULL)
    {
        krb5_free_principal(context, principal);
    }

    if (opt != NULL)
    {
        krb5_get_init_creds_opt_free(context,opt);
    }

    krb5_free_cred_contents(context, &creds);

    if (context != NULL)
    {
        krb5_free_context(context);
    }

    return dwError;
}
示例#12
0
krb5_error_code
kcm_ccache_acquire(krb5_context context,
		   kcm_ccache ccache,
		   krb5_creds **credp)
{
    krb5_error_code ret = 0;
    krb5_creds cred;
    krb5_const_realm realm;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_ccache_data ccdata;
    char *in_tkt_service = NULL;

    memset(&cred, 0, sizeof(cred));

    KCM_ASSERT_VALID(ccache);

    /* We need a cached key or keytab to acquire credentials */
    if (ccache->flags & KCM_FLAGS_USE_CACHED_KEY) {
	if (ccache->key.keyblock.keyvalue.length == 0)
	    krb5_abortx(context,
			"kcm_ccache_acquire: KCM_FLAGS_USE_CACHED_KEY without key");
    } else if (ccache->flags & KCM_FLAGS_USE_KEYTAB) {
	if (ccache->key.keytab == NULL)
	    krb5_abortx(context,
			"kcm_ccache_acquire: KCM_FLAGS_USE_KEYTAB without keytab");
    } else {
	kcm_log(0, "Cannot acquire initial credentials for cache %s without key",
		ccache->name);
	return KRB5_FCC_INTERNAL;
    }
	
    HEIMDAL_MUTEX_lock(&ccache->mutex);

    /* Fake up an internal ccache */
    kcm_internal_ccache(context, ccache, &ccdata);

    /* Now, actually acquire the creds */
    if (ccache->server != NULL) {
	ret = krb5_unparse_name(context, ccache->server, &in_tkt_service);
	if (ret) {
	    kcm_log(0, "Failed to unparse service principal name for cache %s: %s",
		    ccache->name, krb5_get_err_text(context, ret));
	    return ret;
	}
    }

    realm = krb5_principal_get_realm(context, ccache->client);

    ret = krb5_get_init_creds_opt_alloc(context, &opt);
    if (ret)
	goto out;
    krb5_get_init_creds_opt_set_default_flags(context, "kcm", realm, opt);
    if (ccache->tkt_life != 0)
	krb5_get_init_creds_opt_set_tkt_life(opt, ccache->tkt_life);
    if (ccache->renew_life != 0)
	krb5_get_init_creds_opt_set_renew_life(opt, ccache->renew_life);

    if (ccache->flags & KCM_FLAGS_USE_CACHED_KEY) {
	ret = krb5_get_init_creds_keyblock(context,
					   &cred,
					   ccache->client,
					   &ccache->key.keyblock,
					   0,
					   in_tkt_service,
					   opt);
    } else {
	/* loosely based on lib/krb5/init_creds_pw.c */
	ret = krb5_get_init_creds_keytab(context,
					 &cred,
					 ccache->client,
					 ccache->key.keytab,
					 0,
					 in_tkt_service,
					 opt);
    }

    if (ret) {
	kcm_log(0, "Failed to acquire credentials for cache %s: %s",
		ccache->name, krb5_get_err_text(context, ret));
	if (in_tkt_service != NULL)
	    free(in_tkt_service);
	goto out;
    }

    if (in_tkt_service != NULL)
	free(in_tkt_service);

    /* Swap them in */
    kcm_ccache_remove_creds_internal(context, ccache);

    ret = kcm_ccache_store_cred_internal(context, ccache, &cred, 0, credp);
    if (ret) {
	kcm_log(0, "Failed to store credentials for cache %s: %s",
		ccache->name, krb5_get_err_text(context, ret));
	krb5_free_cred_contents(context, &cred);
	goto out;
    }

out:
    if (opt)
	krb5_get_init_creds_opt_free(context, opt);

    HEIMDAL_MUTEX_unlock(&ccache->mutex);

    return ret;
}
示例#13
0
int
main(int argc, char **argv)
{
    krb5_context ctx;
    krb5_ccache in_ccache, out_ccache, armor_ccache;
    krb5_get_init_creds_opt *opt;
    char *user, *password, *armor_ccname = NULL, *in_ccname = NULL, *perr;
    const char *err;
    krb5_principal client;
    krb5_creds creds;
    krb5_flags fast_flags;
    krb5_error_code ret;
    int c;

    while ((c = getopt(argc, argv, "I:A:")) != -1) {
        switch (c) {
        case 'A':
            armor_ccname = optarg;
            break;
        case 'I':
            in_ccname = optarg;
            break;
        }
    }
    if (argc - optind < 2) {
        fprintf(stderr, "Usage: %s [-A armor_ccache] [-I in_ccache] "
                "username password\n", argv[0]);
        return 1;
    }
    user = argv[optind];
    password = argv[optind + 1];

    bail_on_err(NULL, "Error initializing Kerberos", krb5_init_context(&ctx));
    bail_on_err(ctx, "Error allocating space for get_init_creds options",
                krb5_get_init_creds_opt_alloc(ctx, &opt));
    if (in_ccname != NULL) {
        bail_on_err(ctx, "Error resolving input ccache",
                    krb5_cc_resolve(ctx, in_ccname, &in_ccache));
        bail_on_err(ctx, "Error setting input_ccache option",
                    krb5_get_init_creds_opt_set_in_ccache(ctx, opt,
                                                          in_ccache));
    } else {
        in_ccache = NULL;
    }
    if (armor_ccname != NULL) {
        bail_on_err(ctx, "Error resolving armor ccache",
                    krb5_cc_resolve(ctx, armor_ccname, &armor_ccache));
        bail_on_err(ctx, "Error setting fast_ccache option",
                    krb5_get_init_creds_opt_set_fast_ccache(ctx, opt,
                                                            armor_ccache));
        fast_flags = KRB5_FAST_REQUIRED;
        bail_on_err(ctx, "Error setting option to force use of FAST",
                    krb5_get_init_creds_opt_set_fast_flags(ctx, opt,
                                                           fast_flags));
    } else {
        armor_ccache = NULL;
    }
    bail_on_err(ctx, "Error resolving output (default) ccache",
                krb5_cc_default(ctx, &out_ccache));
    bail_on_err(ctx, "Error setting output ccache option",
                krb5_get_init_creds_opt_set_out_ccache(ctx, opt, out_ccache));
    if (asprintf(&perr, "Error parsing principal name \"%s\"", user) < 0)
        abort();
    bail_on_err(ctx, perr, krb5_parse_name(ctx, user, &client));
    ret = krb5_get_init_creds_password(ctx, &creds, client, password,
                                       prompter_cb, NULL, 0, NULL, opt);
    if (ret) {
        err = krb5_get_error_message(ctx, ret);
        printf("%s\n", err);
        krb5_free_error_message(ctx, err);
    } else {
        krb5_free_cred_contents(ctx, &creds);
    }
    krb5_get_init_creds_opt_free(ctx, opt);
    krb5_free_principal(ctx, client);
    krb5_cc_close(ctx, out_ccache);
    if (armor_ccache != NULL)
        krb5_cc_close(ctx, armor_ccache);
    if (in_ccache != NULL)
        krb5_cc_close(ctx, in_ccache);
    krb5_free_context(ctx);
    free(perr);
    return ret ? (ret - KRB5KDC_ERR_NONE) : 0;
}
示例#14
0
文件: setkey-test.c 项目: PADL/krb5
int
main(int argc, char **argv)
{
    krb5_context context;
    krb5_keytab kt;
    krb5_keytab_entry ktent;
    krb5_encrypt_block eblock;
    krb5_creds my_creds;
    krb5_get_init_creds_opt *opt;
    kadm5_principal_ent_rec princ_ent;
    krb5_principal princ, server;
    char pw[16];
    char *whoami, *principal, *authprinc, *authpwd;
    krb5_data pwdata;
    void *handle;
    int ret, test, encnum;
    unsigned int i;

    whoami = argv[0];

    if (argc < 2 || argc > 4) {
        fprintf(stderr, "Usage: %s principal [authuser] [authpwd]\n", whoami);
        exit(1);
    }
    principal = argv[1];
    authprinc = (argc > 2) ? argv[2] : argv[0];
    authpwd = (argc > 3) ? argv[3] : NULL;

    /*
     * Setup.  Initialize data structures, open keytab, open connection
     * to kadm5 server.
     */

    memset(&context, 0, sizeof(context));
    kadm5_init_krb5_context(&context);

    ret = krb5_parse_name(context, principal, &princ);
    if (ret) {
        com_err(whoami, ret, "while parsing principal name %s", principal);
        exit(1);
    }

    if((ret = krb5_build_principal_ext(context, &server,
                                       krb5_princ_realm(kcontext, princ)->length,
                                       krb5_princ_realm(kcontext, princ)->data,
                                       tgtname.length, tgtname.data,
                                       krb5_princ_realm(kcontext, princ)->length,
                                       krb5_princ_realm(kcontext, princ)->data,
                                       0))) {
        com_err(whoami, ret, "while building server name");
        exit(1);
    }

    ret = krb5_kt_default(context, &kt);
    if (ret) {
        com_err(whoami, ret, "while opening keytab");
        exit(1);
    }

    ret = kadm5_init(context, authprinc, authpwd, KADM5_ADMIN_SERVICE, NULL,
                     KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, NULL,
                     &handle);
    if (ret) {
        com_err(whoami, ret, "while initializing connection");
        exit(1);
    }

    /* these pw's don't need to be secure, just different every time */
    SRAND((RAND_TYPE)time((void *) NULL));
    pwdata.data = pw;
    pwdata.length = sizeof(pw);

    /*
     * For each test:
     *
     * For each enctype in the test, construct a random password/key.
     * Assign all keys to principal with kadm5_setkey_principal.  Add
     * each key to the keytab, and acquire an initial ticket with the
     * keytab (XXX can I specify the kvno explicitly?).  If
     * krb5_get_init_creds_keytab succeeds, then the keys were set
     * successfully.
     */
    for (test = 0; tests[test] != NULL; test++) {
        krb5_keyblock *testp = tests[test];
        kadm5_key_data *extracted;
        int n_extracted, match;
        printf("+ Test %d:\n", test);

        for (encnum = 0; testp[encnum].magic != -1; encnum++) {
            for (i = 0; i < sizeof(pw); i++)
                pw[i] = (RAND() % 26) + '0'; /* XXX */

            krb5_use_enctype(context, &eblock, testp[encnum].enctype);
            ret = krb5_string_to_key(context, &eblock, &testp[encnum],
                                     &pwdata, NULL);
            if (ret) {
                com_err(whoami, ret, "while converting string to key");
                exit(1);
            }
        }

        /* now, encnum == # of keyblocks in testp */
        ret = kadm5_setkey_principal(handle, princ, testp, encnum);
        if (ret) {
            com_err(whoami, ret, "while setting keys");
            exit(1);
        }

        ret = kadm5_get_principal(handle, princ, &princ_ent, KADM5_KVNO);
        if (ret) {
            com_err(whoami, ret, "while retrieving principal");
            exit(1);
        }

        ret = kadm5_get_principal_keys(handle, princ, 0, &extracted,
                                       &n_extracted);
        if (ret) {
            com_err(whoami, ret, "while extracting keys");
            exit(1);
        }

        for (encnum = 0; testp[encnum].magic != -1; encnum++) {
            printf("+   enctype %d\n", testp[encnum].enctype);

            for (match = 0; match < n_extracted; match++) {
                if (extracted[match].key.enctype == testp[encnum].enctype)
                    break;
            }
            if (match >= n_extracted) {
                com_err(whoami, KRB5_WRONG_ETYPE, "while matching enctypes");
                exit(1);
            }
            if (extracted[match].key.length != testp[encnum].length ||
                memcmp(extracted[match].key.contents, testp[encnum].contents,
                       testp[encnum].length) != 0) {
                com_err(whoami, KRB5_KDB_NO_MATCHING_KEY, "verifying keys");
                exit(1);
            }

            memset(&ktent, 0, sizeof(ktent));
            ktent.principal = princ;
            ktent.key = testp[encnum];
            ktent.vno = princ_ent.kvno;

            ret = krb5_kt_add_entry(context, kt, &ktent);
            if (ret) {
                com_err(whoami, ret, "while adding keytab entry");
                exit(1);
            }

            memset(&my_creds, 0, sizeof(my_creds));
            my_creds.client = princ;
            my_creds.server = server;

            ktypes[0] = testp[encnum].enctype;
            ret = krb5_get_init_creds_opt_alloc(context, &opt);
            if (ret) {
                com_err(whoami, ret, "while allocating gic opts");
                exit(1);
            }
            krb5_get_init_creds_opt_set_etype_list(opt, ktypes, 1);
            ret = krb5_get_init_creds_keytab(context, &my_creds, princ,
                                             kt, 0, NULL /* in_tkt_service */,
                                             opt);
            krb5_get_init_creds_opt_free(context, opt);
            if (ret) {
                com_err(whoami, ret, "while acquiring initial ticket");
                exit(1);
            }
            krb5_free_cred_contents(context, &my_creds);

            /* since I can't specify enctype explicitly ... */
            ret = krb5_kt_remove_entry(context, kt, &ktent);
            if (ret) {
                com_err(whoami, ret, "while removing keytab entry");
                exit(1);
            }
        }

        (void)kadm5_free_kadm5_key_data(context, n_extracted, extracted);
    }

    ret = krb5_kt_close(context, kt);
    if (ret) {
        com_err(whoami, ret, "while closing keytab");
        exit(1);
    }

    ret = kadm5_destroy(handle);
    if (ret) {
        com_err(whoami, ret, "while closing kadmin connection");
        exit(1);
    }

    krb5_free_principal(context, princ);
    krb5_free_principal(context, server);
    krb5_free_context(context);
    return 0;
}
示例#15
0
static int
krb5_verify_password (POP *p)
{
    krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
    krb5_get_init_creds_opt *get_options;
    krb5_verify_init_creds_opt verify_options;
    krb5_error_code ret;
    krb5_principal client, server;
    krb5_creds creds;

    ret = krb5_get_init_creds_opt_alloc (p->context, &get_options);
    if (ret) {
	pop_log(p, POP_PRIORITY, "krb5_get_init_creds_opt_alloc: %s",
		krb5_get_err_text (p->context, ret));
	return 1;
    }

    krb5_get_init_creds_opt_set_preauth_list (get_options,
					      pre_auth_types,
					      1);

    krb5_verify_init_creds_opt_init (&verify_options);

    ret = krb5_parse_name (p->context, p->user, &client);
    if (ret) {
	krb5_get_init_creds_opt_free(p->context, get_options);
	pop_log(p, POP_PRIORITY, "krb5_parse_name: %s",
		krb5_get_err_text (p->context, ret));
	return 1;
    }

    ret = krb5_get_init_creds_password (p->context,
					&creds,
					client,
					p->pop_parm[1],
					NULL,
					NULL,
					0,
					NULL,
					get_options);
    krb5_get_init_creds_opt_free(p->context, get_options);
    if (ret) {
	pop_log(p, POP_PRIORITY,
		"krb5_get_init_creds_password: %s",
		krb5_get_err_text (p->context, ret));
	return 1;
    }

    ret = krb5_sname_to_principal (p->context,
				   p->myhost,
				   "pop",
				   KRB5_NT_SRV_HST,
				   &server);
    if (ret) {
	pop_log(p, POP_PRIORITY,
		"krb5_get_init_creds_password: %s",
		krb5_get_err_text (p->context, ret));
	return 1;
    }

    ret = krb5_verify_init_creds (p->context,
				  &creds,
				  server,
				  NULL,
				  NULL,
				  &verify_options);
    krb5_free_principal (p->context, client);
    krb5_free_principal (p->context, server);
    krb5_free_cred_contents (p->context, &creds);
    return ret;
}
示例#16
0
int
main(int argc, char **argv)
{
    krb5_context context;
    krb5_ccache ccache;
    krb5_get_init_creds_opt *opts;
    krb5_principal principal;
    krb5_creds creds;
    krb5_error_code err;
    const char *errmsg;
    char *opt, *val;
    struct responder_data response;
    int c;

    err = krb5_init_context(&context);
    if (err != 0) {
        fprintf(stderr, "error starting Kerberos: %s\n", error_message(err));
        return err;
    }
    err = krb5_get_init_creds_opt_alloc(context, &opts);
    if (err != 0) {
        fprintf(stderr, "error initializing options: %s\n",
                error_message(err));
        return err;
    }
    err = krb5_cc_default(context, &ccache);
    if (err != 0) {
        fprintf(stderr, "error resolving default ccache: %s\n",
                error_message(err));
        return err;
    }
    err = krb5_get_init_creds_opt_set_out_ccache(context, opts, ccache);
    if (err != 0) {
        fprintf(stderr, "error setting output ccache: %s\n",
                error_message(err));
        return err;
    }

    memset(&response, 0, sizeof(response));
    while ((c = getopt(argc, argv, "X:x:cr:p:")) != -1) {
        switch (c) {
        case 'X':
            /* Like kinit, set a generic preauth option. */
            opt = strdup(optarg);
            val = opt + strcspn(opt, "=");
            if (*val != '\0') {
                *val++ = '\0';
            }
            err = krb5_get_init_creds_opt_set_pa(context, opts, opt, val);
            if (err != 0) {
                fprintf(stderr, "error setting option \"%s\": %s\n", opt,
                        error_message(err));
                return err;
            }
            free(opt);
            break;
        case 'x':
            /* Check that a particular question has a specific challenge. */
            response.challenge = optarg;
            break;
        case 'c':
            /* Note that we want a dump of the PKINIT challenge structure. */
            response.print_pkinit_challenge = TRUE;
            break;
        case 'r':
            /* Set a verbatim response for a verbatim challenge. */
            response.response = optarg;
            break;
        case 'p':
            /* Set a PKINIT answer for a specific PKINIT identity. */
            response.pkinit_answer = optarg;
            break;
        case 'o':
            /* Set an OTP answer for a specific OTP tokeninfo. */
            response.otp_answer = optarg;
            break;
        }
    }

    if (argc > optind) {
        err = krb5_parse_name(context, argv[optind], &principal);
        if (err != 0) {
            fprintf(stderr, "error parsing name \"%s\": %s", argv[optind],
                    error_message(err));
            return err;
        }
    } else {
        fprintf(stderr, "error: no principal name provided\n");
        return -1;
    }

    err = krb5_get_init_creds_opt_set_responder(context, opts,
                                                responder, &response);
    if (err != 0) {
        fprintf(stderr, "error setting responder: %s\n", error_message(err));
        return err;
    }
    memset(&creds, 0, sizeof(creds));
    err = krb5_get_init_creds_password(context, &creds, principal, NULL,
                                       NULL, NULL, 0, NULL, opts);
    if (err == 0)
        krb5_free_cred_contents(context, &creds);
    krb5_free_principal(context, principal);
    krb5_get_init_creds_opt_free(context, opts);
    krb5_cc_close(context, ccache);

    if (!response.called) {
        fprintf(stderr, "error: responder callback wasn't called\n");
        err = 1;
    } else if (err) {
        errmsg = krb5_get_error_message(context, err);
        fprintf(stderr, "error: krb5_get_init_creds_password failed: %s\n",
                errmsg);
        krb5_free_error_message(context, errmsg);
        err = 2;
    }
    krb5_free_context(context);
    return err;
}
示例#17
0
/*
 * Obtain credentials via a key in the keytab given
 * a keytab handle and a gssd_k5_kt_princ structure.
 * Checks to see if current credentials are expired,
 * if not, uses the keytab to obtain new credentials.
 *
 * Returns:
 *	0 => success (or credentials have not expired)
 *	nonzero => error
 */
static int gssd_get_single_krb5_cred(krb5_context context, krb5_keytab kt,
				     struct gssd_k5_kt_princ *ple, int nocache)
{
#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
	krb5_get_init_creds_opt *init_opts = NULL;
#else
	krb5_get_init_creds_opt options;
#endif
	krb5_get_init_creds_opt *opts;
	krb5_creds my_creds;
	krb5_ccache ccache = NULL;
	char kt_name[BUFSIZ];
	char cc_name[BUFSIZ];
	int code;
	time_t now = time(0);
	char *cache_type;
	char *pname = NULL;
	char *k5err = NULL;

	memset(&my_creds, 0, sizeof(my_creds));

	if (ple->ccname && ple->endtime > now && !nocache) {
		printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
			 ple->ccname, ple->endtime);
		code = 0;
		goto out;
	}

	code = krb5_kt_get_name(context, kt, kt_name, BUFSIZ);
	if (code != 0) {
		printerr(0,
			 "ERROR: Unable to get keytab name in "
			 "gssd_get_single_krb5_cred\n");
		goto out;
	}

	if ((krb5_unparse_name(context, ple->princ, &pname)))
		pname = NULL;

#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
	code = krb5_get_init_creds_opt_alloc(context, &init_opts);
	if (code) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s allocating gic options\n", k5err);
		goto out;
	}
	if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1))
		printerr(1,
			 "WARNING: Unable to set option for addressless "
			 "tickets.  May have problems behind a NAT.\n");
#ifdef TEST_SHORT_LIFETIME
	/* set a short lifetime (for debugging only!) */
	printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
	krb5_get_init_creds_opt_set_tkt_life(init_opts, 5 * 60);
#endif
	opts = init_opts;

#else /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS */

	krb5_get_init_creds_opt_init(&options);
	krb5_get_init_creds_opt_set_address_list(&options, NULL);
#ifdef TEST_SHORT_LIFETIME
	/* set a short lifetime (for debugging only!) */
	printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
	krb5_get_init_creds_opt_set_tkt_life(&options, 5 * 60);
#endif
	opts = &options;
#endif

	code = krb5_get_init_creds_keytab(context, &my_creds,
					  ple->princ, kt, 0,
					  NULL, opts);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(1,
			 "WARNING: %s while getting initial ticket for "
			 "principal '%s' using keytab '%s'\n", k5err,
			 pname ? pname : "<unparsable>", kt_name);
		goto out;
	}

	/*
	 * Initialize cache file which we're going to be using
	 */

	if (use_memcache)
		cache_type = "MEMORY";
	else
		cache_type = "FILE";
	snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s", cache_type,
		 ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX,
		 GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
	ple->endtime = my_creds.times.endtime;
	if (ple->ccname != NULL)
		gsh_free(ple->ccname);
	ple->ccname = gsh_strdup(cc_name);
	if (ple->ccname == NULL) {
		printerr(0,
			 "ERROR: no storage to duplicate credentials "
			 "cache name '%s'\n", cc_name);
		code = ENOMEM;
		goto out;
	}
	code = krb5_cc_resolve(context, cc_name, &ccache);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s while opening credential cache '%s'\n",
			 k5err, cc_name);
		goto out;
	}
	code = krb5_cc_initialize(context, ccache, ple->princ);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0,
			 "ERROR: %s while initializing credential "
			 "cache '%s'\n", k5err, cc_name);
	}
	code = krb5_cc_store_cred(context, ccache, &my_creds);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s while storing credentials in '%s'\n",
			 k5err, cc_name);
		goto out;
	}
	/* if we get this far, let gss mech know */
	gssd_set_krb5_ccache_name(cc_name);
	code = 0;
	printerr(2,
		 "Successfully obtained machine credentials for "
		 "principal '%s' stored in ccache '%s'\n", pname, cc_name);
 out:
#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
	if (init_opts)
		krb5_get_init_creds_opt_free(context, init_opts);
#endif
	if (pname)
		k5_free_unparsed_name(context, pname);
	if (ccache)
		krb5_cc_close(context, ccache);
	krb5_free_cred_contents(context, &my_creds);
	gsh_free(k5err);
	return code;
}
示例#18
0
static krb5_error_code
get_init_creds_common(krb5_context context,
		      krb5_principal client,
		      krb5_deltat start_time,
		      krb5_get_init_creds_opt *options,
		      krb5_init_creds_context ctx)
{
    krb5_get_init_creds_opt *default_opt = NULL;
    krb5_error_code ret;
    krb5_enctype *etypes;
    krb5_preauthtype *pre_auth_types;

    memset(ctx, 0, sizeof(*ctx));

    if (options == NULL) {
	const char *realm = krb5_principal_get_realm(context, client);

        krb5_get_init_creds_opt_alloc (context, &default_opt);
	options = default_opt;
	krb5_get_init_creds_opt_set_default_flags(context, NULL, realm, options);
    }

    if (options->opt_private) {
	if (options->opt_private->password) {
	    ret = krb5_init_creds_set_password(context, ctx, 
					       options->opt_private->password);
	    if (ret)
		goto out;
	}

	ctx->keyproc = options->opt_private->key_proc;
	ctx->req_pac = options->opt_private->req_pac;
	ctx->pk_init_ctx = options->opt_private->pk_init_ctx;
	ctx->ic_flags = options->opt_private->flags;
    } else
	ctx->req_pac = KRB5_INIT_CREDS_TRISTATE_UNSET;

    if (ctx->keyproc == NULL)
	ctx->keyproc = default_s2k_func;

    /* Enterprise name implicitly turns on canonicalize */
    if ((ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) || 
	krb5_principal_get_type(context, client) == KRB5_NT_ENTERPRISE_PRINCIPAL)
	ctx->flags.canonicalize = 1;

    ctx->pre_auth_types = NULL;
    ctx->addrs = NULL;
    ctx->etypes = NULL;
    ctx->pre_auth_types = NULL;

    ret = init_cred(context, &ctx->cred, client, start_time, options);
    if (ret) {
	if (default_opt)
	    krb5_get_init_creds_opt_free(context, default_opt);
	return ret;
    }

    ret = krb5_init_creds_set_service(context, ctx, NULL);
    if (ret)
	goto out;

    if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
	ctx->flags.forwardable = options->forwardable;

    if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE)
	ctx->flags.proxiable = options->proxiable;

    if (start_time)
	ctx->flags.postdated = 1;
    if (ctx->cred.times.renew_till)
	ctx->flags.renewable = 1;
    if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) {
	ctx->addrs = options->address_list;
    } else if (options->opt_private) {
	switch (options->opt_private->addressless) {
	case KRB5_INIT_CREDS_TRISTATE_UNSET:
#if KRB5_ADDRESSLESS_DEFAULT == TRUE
	    ctx->addrs = &no_addrs;
#else
	    ctx->addrs = NULL;
#endif
	    break;
	case KRB5_INIT_CREDS_TRISTATE_FALSE:
	    ctx->addrs = NULL;
	    break;
	case KRB5_INIT_CREDS_TRISTATE_TRUE:
	    ctx->addrs = &no_addrs;
	    break;
	}
    }
    if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) {
	etypes = malloc((options->etype_list_length + 1)
			* sizeof(krb5_enctype));
	if (etypes == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	    goto out;
	}
	memcpy (etypes, options->etype_list,
		options->etype_list_length * sizeof(krb5_enctype));
	etypes[options->etype_list_length] = ETYPE_NULL;
	ctx->etypes = etypes;
    }
    if (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
	pre_auth_types = malloc((options->preauth_list_length + 1)
				* sizeof(krb5_preauthtype));
	if (pre_auth_types == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	    goto out;
	}
	memcpy (pre_auth_types, options->preauth_list,
		options->preauth_list_length * sizeof(krb5_preauthtype));
	pre_auth_types[options->preauth_list_length] = KRB5_PADATA_NONE;
	ctx->pre_auth_types = pre_auth_types;
    }
    if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS)
	ctx->flags.request_anonymous = options->anonymous;
    if (default_opt)
        krb5_get_init_creds_opt_free(context, default_opt);
    return 0;
 out:
    if (default_opt)
	krb5_get_init_creds_opt_free(context, default_opt);
    return ret;
}
示例#19
0
文件: ksetpwd.c 项目: Akasurde/krb5
static kbrccache_t userinitcontext(
    const char * user, const char * domain, const char * passwd, const char * cachename, int initialize,
    int * outError )
{
    krb5_context    kcontext = 0;
    krb5_ccache             kcache = 0;
    krb5_creds              kcreds;
    krb5_principal  kme = 0;
    krb5_error_code kres;
    char *                  pPass = strdup( passwd );
    char *                  pName = NULL;
    char *                  pCacheName = NULL;
    int                             numCreds = 0;

    memset( &kcreds, 0, sizeof(kcreds) );
    kres = krb5_init_context( &kcontext );
    if( kres )
        goto return_error;
    if( domain )
        kres = krb5_build_principal( kcontext, &kme, strlen(domain), domain, user, (char *) 0 );
    else
        kres = krb5_parse_name( kcontext, user, &kme );
    if( kres )
        goto fail;
    krb5_unparse_name( kcontext, kme, &pName );
    if( cachename )
    {
        if (asprintf(&pCacheName, "%s%s", cachename, pName) < 0)
        {
            kres = KRB5_CC_NOMEM;
            goto fail;
        }
        kres = krb5_cc_resolve( kcontext, pCacheName, &kcache );
        if( kres )
        {
            kres = krb5_cc_resolve( kcontext, CCACHE_PREFIX_DEFAULT, &kcache );
            if( kres == 0 )
                pCacheName = strdup(CCACHE_PREFIX_DEFAULT);
        }
    }
    else
    {
        kres = krb5_cc_default( kcontext, &kcache );
        pCacheName = strdup( krb5_cc_get_name( kcontext, kcache ) );
    }
    if( kres )
    {
        krb5_free_context(kcontext);
        goto return_error;
    }
    if( initialize )
        krb5_cc_initialize( kcontext, kcache, kme );
    if( kres == 0 && user && passwd )
    {
        long timeneeded = time(0L) +TKTTIMELEFT;
        int have_credentials = 0;
        krb5_cc_cursor cc_curs = NULL;
        numCreds = 0;
        if( (kres=krb5_cc_start_seq_get(kcontext, kcache, &cc_curs)) >= 0 )
        {
            while( (kres=krb5_cc_next_cred(kcontext, kcache, &cc_curs, &kcreds))== 0)
            {
                numCreds++;
                if( krb5_principal_compare( kcontext, kme, kcreds.client ) )
                {
                    if( kcreds.ticket_flags & TKT_FLG_INITIAL && kcreds.times.endtime>timeneeded )
                        have_credentials = 1;
                }
                krb5_free_cred_contents( kcontext, &kcreds );
                if( have_credentials )
                    break;
            }
            krb5_cc_end_seq_get( kcontext, kcache, &cc_curs );
        }
        else
        {
            const char * errmsg = error_message(kres);
            fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg );
        }
        if( kres != 0 || have_credentials == 0 )
        {
            krb5_get_init_creds_opt *options = NULL;
            kres = krb5_get_init_creds_opt_alloc(kcontext, &options);
            if ( kres == 0 )
            {
                get_init_creds_opt_init(options);
/*
** no valid credentials - get new ones
*/
                kres = krb5_get_init_creds_password( kcontext, &kcreds, kme, pPass,
                                                     NULL /*prompter*/,
                                                     NULL /*data*/,
                                                     0 /*starttime*/,
                                                     0 /*in_tkt_service*/,
                                                     options /*options*/ );
            }
            if( kres == 0 )
            {
                if( numCreds <= 0 )
                    kres = krb5_cc_initialize( kcontext, kcache, kme );
                if( kres == 0 )
                    kres = krb5_cc_store_cred( kcontext, kcache, &kcreds );
                if( kres == 0 )
                    have_credentials = 1;
            }
            krb5_get_init_creds_opt_free(kcontext, options);
        }
#ifdef NOTUSED
        if( have_credentials )
        {
            int mstat;
            kres = gss_krb5_ccache_name( &mstat, pCacheName, NULL );
            if( getenv( ENV_DEBUG_LDAPKERB ) )
                fprintf( stderr, "gss credentials cache set to %s(%d)\n", pCacheName, kres );
        }
#endif
        krb5_cc_close( kcontext, kcache );
    }
fail:
    if( kres )
    {
        const char * errmsg = error_message(kres);
        fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg );
    }
    krb5_free_principal( kcontext, kme );
    krb5_free_cred_contents( kcontext, &kcreds );
    if( pName )
        free( pName );
    free(pPass);
    krb5_free_context(kcontext);

return_error:
    if( kres )
    {
        if( pCacheName )
        {
            free(pCacheName);
            pCacheName = NULL;
        }
    }
    if( outError )
        *outError = kres;
    return pCacheName;
}
示例#20
0
static krb5_error_code
change_password (krb5_context context,
		 krb5_principal client,
		 const char *password,
		 char *newpw,
		 size_t newpw_sz,
		 krb5_prompter_fct prompter,
		 void *data,
		 krb5_get_init_creds_opt *old_options)
{
    krb5_prompt prompts[2];
    krb5_error_code ret;
    krb5_creds cpw_cred;
    char buf1[BUFSIZ], buf2[BUFSIZ];
    krb5_data password_data[2];
    int result_code;
    krb5_data result_code_string;
    krb5_data result_string;
    char *p;
    krb5_get_init_creds_opt *options;

    memset (&cpw_cred, 0, sizeof(cpw_cred));

    ret = krb5_get_init_creds_opt_alloc(context, &options);
    if (ret)
        return ret;
    krb5_get_init_creds_opt_set_tkt_life (options, 60);
    krb5_get_init_creds_opt_set_forwardable (options, FALSE);
    krb5_get_init_creds_opt_set_proxiable (options, FALSE);
    if (old_options && old_options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)
	krb5_get_init_creds_opt_set_preauth_list (options,
						  old_options->preauth_list,
						  old_options->preauth_list_length);

    krb5_data_zero (&result_code_string);
    krb5_data_zero (&result_string);

    ret = krb5_get_init_creds_password (context,
					&cpw_cred,
					client,
					password,
					prompter,
					data,
					0,
					"kadmin/changepw",
					options);
    krb5_get_init_creds_opt_free(context, options);
    if (ret)
	goto out;

    for(;;) {
	password_data[0].data   = buf1;
	password_data[0].length = sizeof(buf1);

	prompts[0].hidden = 1;
	prompts[0].prompt = "New password: "******"Repeat new password: "******"Changing password",
			   2, prompts);
	if (ret) {
	    memset (buf1, 0, sizeof(buf1));
	    memset (buf2, 0, sizeof(buf2));
	    goto out;
	}

	if (strcmp (buf1, buf2) == 0)
	    break;
	memset (buf1, 0, sizeof(buf1));
	memset (buf2, 0, sizeof(buf2));
    }

    ret = krb5_set_password (context,
			     &cpw_cred,
			     buf1,
			     client,
			     &result_code,
			     &result_code_string,
			     &result_string);
    if (ret)
	goto out;
    asprintf (&p, "%s: %.*s\n",
	      result_code ? "Error" : "Success",
	      (int)result_string.length,
	      result_string.length > 0 ? (char*)result_string.data : "");

    /* return the result */
    (*prompter) (context, data, NULL, p, 0, NULL);

    free (p);
    if (result_code == 0) {
	strlcpy (newpw, buf1, newpw_sz);
	ret = 0;
    } else {
	ret = ENOTTY;
	krb5_set_error_message(context, ret,
			       N_("failed changing password", ""));
    }

out:
    memset (buf1, 0, sizeof(buf1));
    memset (buf2, 0, sizeof(buf2));
    krb5_data_free (&result_string);
    krb5_data_free (&result_code_string);
    krb5_free_cred_contents (context, &cpw_cred);
    return ret;
}
示例#21
0
int
main (int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_principal principal;
    krb5_get_init_creds_opt *opt;
    krb5_ccache id = NULL;
    int exit_value;
    int optidx = 0;

    setprogname(argv[0]);

    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1, args, sizeof(args) / sizeof(args[0]));
    if (help_flag)
	usage(0, args, sizeof(args) / sizeof(args[0]));
    if (version_flag) {
	print_version(NULL);
	return 0;
    }
    argc -= optidx;
    argv += optidx;

    ret = krb5_init_context (&context);
    if (ret)
	errx (1, "krb5_init_context failed: %d", ret);

    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_tkt_life (opt, 300);
    krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
    krb5_get_init_creds_opt_set_proxiable (opt, FALSE);

    if (cred_cache_str) {
	ret = krb5_cc_resolve(context, cred_cache_str, &id);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");
    } else {
	ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_new_unique");
    }

    if (cred_cache_str == NULL) {
	krb5_principal admin_principal = NULL;
	krb5_creds cred;

	if (admin_principal_str) {
	    ret = krb5_parse_name (context, admin_principal_str,
				   &admin_principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_parse_name");
	} else if (argc == 1) {
	    ret = krb5_parse_name (context, argv[0], &admin_principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_parse_name");
	} else {
	    ret = krb5_get_default_principal (context, &admin_principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_get_default_principal");
	}

	ret = krb5_get_init_creds_password (context,
					    &cred,
					    admin_principal,
					    NULL,
					    krb5_prompter_posix,
					    NULL,
					    0,
					    "kadmin/changepw",
					    opt);
	switch (ret) {
	case 0:
	    break;
	case KRB5_LIBOS_PWDINTR :
	    return 1;
	case KRB5KRB_AP_ERR_BAD_INTEGRITY :
	case KRB5KRB_AP_ERR_MODIFIED :
	    krb5_errx(context, 1, "Password incorrect");
	    break;
	default:
	    krb5_err(context, 1, ret, "krb5_get_init_creds");
	}

	krb5_get_init_creds_opt_free(context, opt);

	ret = krb5_cc_initialize(context, id, admin_principal);
	krb5_free_principal(context, admin_principal);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_initialize");

	ret = krb5_cc_store_cred(context, id, &cred);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_store_cred");

	krb5_free_cred_contents (context, &cred);
    }

    if (argc == 0) {
	exit_value = change_password(context, NULL, id);
    } else {
	exit_value = 0;

	while (argc-- > 0) {

	    ret = krb5_parse_name (context, argv[0], &principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_parse_name");

	    ret = change_password(context, principal, id);
	    if (ret)
		exit_value = 1;
	    krb5_free_principal(context, principal);
	    argv++;
	}
    }

    if (cred_cache_str == NULL) {
	ret = krb5_cc_destroy(context, id);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_destroy");
    } else {
	ret = krb5_cc_close(context, id);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_close");
    }

    krb5_free_context (context);
    return exit_value;
}
示例#22
0
static krb5_error_code
get_new_cache(krb5_context context,
	      krb5_principal client,
	      const char *password,
	      krb5_prompter_fct prompter,
	      const char *keytab,
	      const char *server_name,
	      krb5_ccache *ret_cache)
{
    krb5_error_code ret;
    krb5_creds cred;
    krb5_get_init_creds_opt *opt;
    krb5_ccache id;

    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	return ret;

    krb5_get_init_creds_opt_set_default_flags(context, "kadmin",
					      krb5_principal_get_realm(context,
								       client),
					      opt);


    krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
    krb5_get_init_creds_opt_set_proxiable (opt, FALSE);

    if(password == NULL && prompter == NULL) {
	krb5_keytab kt;
	if(keytab == NULL)
	    ret = krb5_kt_default(context, &kt);
	else
	    ret = krb5_kt_resolve(context, keytab, &kt);
	if(ret) {
	    krb5_get_init_creds_opt_free(context, opt);
	    return ret;
	}
	ret = krb5_get_init_creds_keytab (context,
					  &cred,
					  client,
					  kt,
					  0,
					  server_name,
					  opt);
	krb5_kt_close(context, kt);
    } else {
	ret = krb5_get_init_creds_password (context,
					    &cred,
					    client,
					    password,
					    prompter,
					    NULL,
					    0,
					    server_name,
					    opt);
    }
    krb5_get_init_creds_opt_free(context, opt);
    switch(ret){
    case 0:
	break;
    case KRB5_LIBOS_PWDINTR:	/* don't print anything if it was just C-c:ed */
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KRB_AP_ERR_MODIFIED:
	return KADM5_BAD_PASSWORD;
    default:
	return ret;
    }
    ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
    if(ret)
	return ret;
    ret = krb5_cc_initialize (context, id, cred.client);
    if (ret)
	return ret;
    ret = krb5_cc_store_cred (context, id, &cred);
    if (ret)
	return ret;
    krb5_free_cred_contents (context, &cred);
    *ret_cache = id;
    return 0;
}
示例#23
0
static void
generate_requests(const char *filename, unsigned nreq)
{
    krb5_context context;
    krb5_error_code ret;
    int i;
    char **words;
    unsigned nwords, k;

    ret = krb5_init_context(&context);
    if (ret)
	errx (1, "krb5_init_context failed: %d", ret);

    nwords = read_words(filename, &words);

    for (i = 0; i < nreq; ++i) {
	char *name = words[rand() % nwords];
	krb5_get_init_creds_opt *opt;
	krb5_creds cred;
	krb5_principal principal;
	int result_code;
	krb5_data result_code_string, result_string;
	char *old_pwd, *new_pwd;
	int aret;

	krb5_get_init_creds_opt_alloc(context, &opt);
	krb5_get_init_creds_opt_set_tkt_life (opt, 300);
	krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
	krb5_get_init_creds_opt_set_proxiable (opt, FALSE);

	ret = krb5_parse_name(context, name, &principal);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_name %s", name);

	aret = asprintf(&old_pwd, "%s", name);
	if (aret == -1)
	    krb5_errx(context, 1, "out of memory");
	aret = asprintf(&new_pwd, "%s2", name);
	if (aret == -1)
	    krb5_errx(context, 1, "out of memory");

	ret = krb5_get_init_creds_password(context,
					   &cred,
					   principal,
					   old_pwd,
					   nop_prompter,
					   NULL,
					   0,
					   "kadmin/changepw",
					   opt);
	if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY
	    || ret == KRB5KRB_AP_ERR_MODIFIED) {
	    char *tmp;

	    tmp = new_pwd;
	    new_pwd = old_pwd;
	    old_pwd = tmp;

            ret = krb5_get_init_creds_password(context,
                                               &cred,
                                               principal,
                                               old_pwd,
                                               nop_prompter,
                                               NULL,
                                               0,
                                               "kadmin/changepw",
                                               opt);
	}
	if (ret)
	    krb5_err(context, 1, ret, "krb5_get_init_creds_password");

	krb5_free_principal(context, principal);


        ret = krb5_set_password(context,
                                &cred,
                                new_pwd,
                                NULL,
                                &result_code,
                                &result_code_string,
                                &result_string);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_change_password");

	free(old_pwd);
	free(new_pwd);
	krb5_free_cred_contents(context, &cred);
	krb5_get_init_creds_opt_free(context, opt);
    }

    for (k = 0; k < nwords; k++)
        free(words[k]);
    free(words);
}
示例#24
0
文件: hooks.c 项目: INNOAUS/krb5
int
main(int argc, char *argv[])
{
    const char *principal, *password;
    krb5_principal client;
    krb5_get_init_creds_opt *opts;
    krb5_creds creds;
    krb5_error_code ret, test_return_code;

    if (argc != 3) {
        fprintf(stderr, "Usage: %s princname password\n", argv[0]);
        exit(1);
    }
    principal = argv[1];
    password = argv[2];

    check(krb5_init_context(&ctx));
    check(krb5_parse_name(ctx, principal, &client));

    /* Use a send hook to modify an outgoing AS-REQ.  The library will detect
     * the modification in the reply. */
    check(krb5_get_init_creds_opt_alloc(ctx, &opts));
    krb5_get_init_creds_opt_set_canonicalize(opts, 1);
    krb5_set_kdc_send_hook(ctx, test_send_as_req, NULL);
    krb5_set_kdc_recv_hook(ctx, test_recv_as_rep, NULL);
    ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL,
                                       NULL, 0, NULL, opts);
    assert(ret == KRB5_KDCREP_MODIFIED);
    krb5_get_init_creds_opt_free(ctx, opts);

    /* Use a send hook to synthesize a KRB-ERROR reply. */
    krb5_set_kdc_send_hook(ctx, test_send_error, NULL);
    krb5_set_kdc_recv_hook(ctx, test_recv_error, NULL);
    ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL,
                                       NULL, 0, NULL, NULL);
    assert(ret == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN);

    /* Use a recv hook to modify a KDC reply. */
    krb5_set_kdc_send_hook(ctx, NULL, NULL);
    krb5_set_kdc_recv_hook(ctx, test_recv_modify_reply, NULL);
    ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL,
                                       NULL, 0, NULL, NULL);
    assert(ret == KRB5KRB_AP_ERR_MSG_TYPE);

    /* Verify that the user data pointer works in the send hook. */
    test_return_code = KRB5KDC_ERR_PREAUTH_FAILED;
    krb5_set_kdc_send_hook(ctx, test_send_return_value, &test_return_code);
    krb5_set_kdc_recv_hook(ctx, NULL, NULL);
    ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL,
                                        NULL, 0, NULL, NULL);
    assert(ret == KRB5KDC_ERR_PREAUTH_FAILED);

    /* Verify that the user data pointer works in the recv hook. */
    test_return_code = KRB5KDC_ERR_NULL_KEY;
    krb5_set_kdc_send_hook(ctx, NULL, NULL);
    krb5_set_kdc_recv_hook(ctx, test_recv_return_value, &test_return_code);
    ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL,
                                       NULL, 0, NULL, NULL);
    assert(ret == KRB5KDC_ERR_NULL_KEY);

    krb5_free_principal(ctx, client);
    krb5_free_context(ctx);
    return 0;
}
Krb5InitCredsOpt::~Krb5InitCredsOpt() {
  if (options_) {
    krb5_get_init_creds_opt_free(context_, options_);
  }
}
示例#26
0
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_keytab(krb5_context context,
			   krb5_creds *creds,
			   krb5_principal client,
			   krb5_keytab arg_keytab,
			   krb5_deltat start_time,
			   char *in_tkt_service,
			   krb5_get_init_creds_opt *options)
{
   krb5_error_code ret, ret2;
   int use_master;
   krb5_keytab keytab;
   krb5_gic_opt_ext *opte = NULL;

   if (arg_keytab == NULL) {
       if ((ret = krb5_kt_default(context, &keytab)))
	    return ret;
   } else {
       keytab = arg_keytab;
   }

   ret = krb5int_gic_opt_to_opte(context, options, &opte, 1,
				 "krb5_get_init_creds_keytab");
   if (ret)
      return ret;

   /*
    * Solaris Kerberos:
    * If "client" was constructed from krb5_sname_to_princ() it may
    * have a referral realm. This happens when there is no applicable 
    * domain-to-realm mapping in the Kerberos configuration file.
    * If that is the case then the realm of the first principal found
    * in the keytab which matches the client can be used for the client's
    * realm.
    */
   if (krb5_is_referral_realm(&client->realm)) {
	krb5_data realm;
	ret = krb5_kt_find_realm(context, keytab, client, &realm);
	if (ret == 0) {
		krb5_free_data_contents(context, &client->realm);
		client->realm.length = realm.length;
		client->realm.data = realm.data;
	} else {
		/* Try to set a useful error message */
		char *princ = NULL;
		krb5_unparse_name(context, client, &princ);

		krb5_set_error_message(context, ret,
		    gettext("Failed to find realm for %s in keytab"),
		    princ ? princ : "<unknown>");
		if (princ)
			krb5_free_unparsed_name(context, princ);
	}
   }

   if (ret != 0)
	goto cleanup;


   use_master = 0;

   /* first try: get the requested tkt from any kdc */

   ret = krb5_get_init_creds(context, creds, client, NULL, NULL,
			     start_time, in_tkt_service, opte,
			     krb5_get_as_key_keytab, (void *) keytab,
			     &use_master,NULL);

   /* check for success */

   if (ret == 0)
      goto cleanup;

   /* If all the kdc's are unavailable fail */

   if ((ret == KRB5_KDC_UNREACH) || (ret == KRB5_REALM_CANT_RESOLVE))
      goto cleanup;

   /* if the reply did not come from the master kdc, try again with
      the master kdc */

   if (!use_master) {
      use_master = 1;

      ret2 = krb5_get_init_creds(context, creds, client, NULL, NULL,
				 start_time, in_tkt_service, opte,
				 krb5_get_as_key_keytab, (void *) keytab,
				 &use_master, NULL);
      
      if (ret2 == 0) {
	 ret = 0;
	 goto cleanup;
      }

      /* if the master is unreachable, return the error from the
	 slave we were able to contact */

      if ((ret2 == KRB5_KDC_UNREACH) ||
	  (ret2 == KRB5_REALM_CANT_RESOLVE) ||
	  (ret2 == KRB5_REALM_UNKNOWN))
	 goto cleanup;

      ret = ret2;
   }

   /* at this point, we have a response from the master.  Since we don't
      do any prompting or changing for keytabs, that's it. */

cleanup:
   if (opte && krb5_gic_opt_is_shadowed(opte))
       krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
   if (arg_keytab == NULL)
       (void) krb5_kt_close(context, keytab); /* Solaris Kerberos */

   return(ret);
}
示例#27
0
文件: kdc.c 项目: dariaphoebe/heimdal
static krb5_error_code
get_ccache(krb5_context context, int *destroy, krb5_ccache *id)
{
    krb5_principal principal = NULL;
    krb5_error_code ret;
    krb5_keytab kt = NULL;

    *id = NULL;

    if (!issuid()) {
	const char *cache;

	cache = getenv("NTLM_ACCEPTOR_CCACHE");
	if (cache) {
	    ret = krb5_cc_resolve(context, cache, id);
	    if (ret)
		goto out;
	    return 0;
	}
    }

    ret = krb5_sname_to_principal(context, NULL, "host",
				  KRB5_NT_SRV_HST, &principal);
    if (ret)
	goto out;

    ret = krb5_cc_cache_match(context, principal, id);
    if (ret == 0)
	return 0;

    /* did not find in default credcache, lets try default keytab */
    ret = krb5_kt_default(context, &kt);
    if (ret)
	goto out;

    /* XXX check in keytab */
    {
	krb5_get_init_creds_opt *opt;
	krb5_creds cred;

	memset(&cred, 0, sizeof(cred));

	ret = krb5_cc_new_unique(context, "MEMORY", NULL, id);
	if (ret)
	    goto out;
	*destroy = 1;
	ret = krb5_get_init_creds_opt_alloc(context, &opt);
	if (ret)
	    goto out;
	ret = krb5_get_init_creds_keytab (context,
					  &cred,
					  principal,
					  kt,
					  0,
					  NULL,
					  opt);
	krb5_get_init_creds_opt_free(context, opt);
	if (ret)
	    goto out;
	ret = krb5_cc_initialize (context, *id, cred.client);
	if (ret) {
	    krb5_free_cred_contents (context, &cred);
	    goto out;
	}
	ret = krb5_cc_store_cred (context, *id, &cred);
	krb5_free_cred_contents (context, &cred);
	if (ret)
	    goto out;
    }

    krb5_kt_close(context, kt);

    return 0;

out:
    if (*id) {
	if (*destroy)
	    krb5_cc_destroy(context, *id);
	else
	    krb5_cc_close(context, *id);
	*id = NULL;
    }

    if (kt)
	krb5_kt_close(context, kt);

    if (principal)
	krb5_free_principal(context, principal);
    return ret;
}
示例#28
0
/*
 * username, password: Credentials to validate. Null not allowed
 * service: Service principal (e.g. HTTP/somehost.example.org) of key
 *          stored in default keytab which will be used to verify KDC.
 *          Empty string (*not* NULL) will bypass KDC verification
 * return: response->return_code will be
 * 		-1 (AUTH_GSS_ERROR) for error, see response->message
 * 	 	0 for auth fail
 * 	 	1 for auth ok
 */
gss_client_response *authenticate_user_krb5_password(const char *username,
							 const char *password,
							 const char *service)
{
    krb5_context context = NULL;
    krb5_error_code problem;
    krb5_principal user_principal = NULL;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_creds creds;
    bool auth_ok = false;

    gss_client_response *response = NULL;

    if (username == NULL || password == NULL || service == NULL) {
	return other_error("username, password and service must all be non-null");
    }

    memset(&creds, 0, sizeof(creds));

    problem = krb5_init_context(&context);
    if (problem) {
	// can't call krb5_ctx_error without a context...
	response = other_error("unable to initialize krb5 context (%d)", (int)problem);
	goto out;
    }

    problem = krb5_parse_name(context, username, &user_principal);
    if (problem) {
	response = krb5_ctx_error(context, problem);
	goto out;
    }

    problem = krb5_get_init_creds_opt_alloc(context, &opt);
    if (problem) {
	response = krb5_ctx_error(context, problem);
        goto out;
    }

    problem = krb5_get_init_creds_password(context, &creds, user_principal,
                                          (char *)password, NULL,
					  NULL, 0, NULL, opt);

    switch (problem) {
    case 0:
        auth_ok = true;
        break;
    case KRB5KDC_ERR_PREAUTH_FAILED:
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
        /* "expected" error */
        auth_ok = false;
        break;
    default:
	/* unexpected error */
	response = krb5_ctx_error(context, problem);
	break;
    }

    if (auth_ok && strlen(service) > 0) {
	response = verify_krb5_kdc(context, &creds, service);
    }

  out:
    krb5_free_cred_contents(context, &creds);

    if (opt != NULL) {
	krb5_get_init_creds_opt_free(context, opt);
    }

    if (user_principal != NULL) {
	krb5_free_principal(context, user_principal);
    }

    if (context != NULL) {
	krb5_free_context(context);
    }

    if (response == NULL) {
	response = calloc(1, sizeof(gss_client_response));
	if(response == NULL) die1("Memory allocation failed");
	response->return_code = auth_ok ? 1 : 0;
    }

    return response;
}