Ejemplo n.º 1
0
/*
 * This function allows the caller to supply options to preauth
 * plugins.  Preauth plugin modules are given a chance to look
 * at each option at the time this function is called in ordre
 * to check the validity of the option.
 * The 'opt' pointer supplied to this function must have been
 * obtained using krb5_get_init_creds_opt_alloc()
 */
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_pa(krb5_context context,
			       krb5_get_init_creds_opt *opt,
			       const char *attr,
			       const char *value)
{
    krb5_error_code retval;
    krb5_gic_opt_ext *opte;

    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
				     "krb5_get_init_creds_opt_set_pa");
    if (retval)
	return retval;

    /*
     * Copy the option into the extended get_init_creds_opt structure
     */
    retval = add_gic_opt_ext_preauth_data(context, opte, attr, value);
    if (retval)
	return retval;

    /*
     * Give the plugins a chance to look at the option now.
     */
    retval = krb5_preauth_supply_preauth_data(context, opte, attr, value);
    return retval;
}
Ejemplo n.º 2
0
/*
 * This function allows a preauth plugin to obtain preauth
 * options.  The preauth_data returned from this function
 * should be freed by calling krb5_get_init_creds_opt_free_pa().
 *
 * The 'opt' pointer supplied to this function must have been
 * obtained using krb5_get_init_creds_opt_alloc()
 */
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_get_pa(krb5_context context,
			       krb5_get_init_creds_opt *opt,
			       int *num_preauth_data,
			       krb5_gic_opt_pa_data **preauth_data)
{
    krb5_error_code retval;
    krb5_gic_opt_ext *opte;
    krb5_gic_opt_pa_data *p = NULL;
    int i;
    size_t allocsize;

    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
				     "krb5_get_init_creds_opt_get_pa");
    if (retval)
	return retval;

    if (num_preauth_data == NULL || preauth_data == NULL)
	return EINVAL;

    *num_preauth_data = 0;
    *preauth_data = NULL;

    if (opte->opt_private->num_preauth_data == 0)
	return 0;

    allocsize =
	    opte->opt_private->num_preauth_data * sizeof(krb5_gic_opt_pa_data);
    p = malloc(allocsize);
    if (p == NULL)
	return ENOMEM;

    /* Init these to make cleanup easier */
    for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
	p[i].attr = NULL;
	p[i].value = NULL;
    }

    for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
	p[i].attr = strdup(opte->opt_private->preauth_data[i].attr);
	p[i].value = strdup(opte->opt_private->preauth_data[i].value);
	if (p[i].attr == NULL || p[i].value == NULL)
	    goto cleanup;
    }
    *num_preauth_data = i;
    *preauth_data = p;
    return 0;
cleanup:
    for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
	if (p[i].attr != NULL)
	    free(p[i].attr);
	if (p[i].value != NULL)
	    free(p[i].value);
    }
    free(p);
    return ENOMEM;
}
Ejemplo n.º 3
0
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_fast_flags(krb5_context context,
                                       krb5_get_init_creds_opt *opt,
                                       krb5_flags flags)
{
    krb5_error_code retval = 0;
    krb5_gic_opt_ext *opte;

    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
                                     "krb5_get_init_creds_opt_set_fast_flags");
    if (retval)
        return retval;
    opte->opt_private->fast_flags = flags;
    return retval;
}
Ejemplo n.º 4
0
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_out_ccache(krb5_context context,
                                       krb5_get_init_creds_opt *opt,
                                       krb5_ccache ccache)
{
    krb5_error_code retval = 0;
    krb5_gic_opt_ext *opte;

    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
                                     "krb5_get_init_creds_opt_set_out_ccache");
    if (retval)
        return retval;
    opte->opt_private->out_ccache = ccache;
    return 0;
}
Ejemplo n.º 5
0
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_responder(krb5_context context,
                                      krb5_get_init_creds_opt *opt,
                                      krb5_responder_fn responder, void *data)
{
    krb5_error_code ret;
    krb5_gic_opt_ext *opte;

    ret = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
                                  "krb5_get_init_creds_opt_set_responder");
    if (ret)
        return ret;
    opte->opt_private->responder = responder;
    opte->opt_private->responder_data = data;
    return 0;
}
Ejemplo n.º 6
0
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_expire_callback(krb5_context context,
                                            krb5_get_init_creds_opt *opt,
                                            krb5_expire_callback_func cb,
                                            void *data)
{
    krb5_error_code retval = 0;
    krb5_gic_opt_ext *opte;

    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
                                     "krb5_get_init_creds_opt_set_"
                                     "expire_callback");
    if (retval)
        return retval;
    opte->opt_private->expire_cb = cb;
    opte->opt_private->expire_data = data;
    return retval;
}
Ejemplo n.º 7
0
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_fast_ccache_name(krb5_context context,
                                             krb5_get_init_creds_opt *opt,
                                             const char *ccache_name)
{
    krb5_error_code retval = 0;
    krb5_gic_opt_ext *opte;

    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
                                     "krb5_get_init_creds_opt_set_fast_ccache_name");
    if (retval)
        return retval;
    if (opte->opt_private->fast_ccache_name) {
        free(opte->opt_private->fast_ccache_name);
    }
    opte->opt_private->fast_ccache_name = strdup(ccache_name);
    if (opte->opt_private->fast_ccache_name == NULL)
        retval = ENOMEM;
    return retval;
}
Ejemplo n.º 8
0
/*
 * Send an appropriate warning prompter if as_reply indicates that the password
 * is going to expire soon.  If an expire callback was provided, use that
 * instead.
 */
static void
warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
               krb5_prompter_fct prompter, void *data,
               const char *in_tkt_service, krb5_kdc_rep *as_reply)
{
    krb5_error_code ret;
    krb5_timestamp pw_exp, acct_exp, now;
    krb5_boolean is_last_req;
    krb5_deltat delta;
    krb5_gic_opt_ext *opte;
    char ts[256], banner[1024];

    get_expiry_times(as_reply->enc_part2, &pw_exp, &acct_exp, &is_last_req);

    ret = krb5int_gic_opt_to_opte(context, options, &opte, 0, "");
    if (ret == 0 && opte->opt_private->expire_cb != NULL) {
        krb5_expire_callback_func cb = opte->opt_private->expire_cb;
        void *cb_data = opte->opt_private->expire_data;

        /* Invoke the expire callback and don't send prompter warnings. */
        (*cb)(context, cb_data, pw_exp, acct_exp, is_last_req);
        return;
    }

    /* Don't warn if no password expiry value was sent. */
    if (pw_exp == 0)
        return;

    /* Don't warn if the password is being changed. */
    if (in_tkt_service && strcmp(in_tkt_service, "kadmin/changepw") == 0)
        return;

    /*
     * If the expiry time came from a last_req field, assume the KDC wants us
     * to warn.  Otherwise, warn only if the expiry time is less than a week
     * from now.
     */
    ret = krb5_timeofday(context, &now);
    if (ret != 0)
        return;
    if (!is_last_req &&
        (pw_exp < now || (pw_exp - now) > 7 * 24 * 60 * 60))
        return;

    if (!prompter)
        return;

    ret = krb5_timestamp_to_string(pw_exp, ts, sizeof(ts));
    if (ret != 0)
        return;

    delta = pw_exp - now;
    if (delta < 3600) {
        snprintf(banner, sizeof(banner),
                 _("Warning: Your password will expire in less than one hour "
                   "on %s"), ts);
    } else if (delta < 86400*2) {
        snprintf(banner, sizeof(banner),
                 _("Warning: Your password will expire in %d hour%s on %s"),
                 delta / 3600, delta < 7200 ? "" : "s", ts);
    } else {
        snprintf(banner, sizeof(banner),
                 _("Warning: Your password will expire in %d days on %s"),
                 delta / 86400, ts);
    }

    /* PROMPTER_INVOCATION */
    (*prompter)(context, data, 0, banner, 0, 0);
}
Ejemplo n.º 9
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);
}