Пример #1
0
bool_t
xdr_krb5_principal(XDR *xdrs, krb5_principal *objp)
{
    int	    ret;
    char	    *p = NULL;
    krb5_principal  pr = NULL;
    static krb5_context context = NULL;

    /* using a static context here is ugly, but should work
       ok, and the other solutions are even uglier */

    if (!context &&
	kadm5_init_krb5_context(&context))
       return(FALSE);

    switch(xdrs->x_op) {
    case XDR_ENCODE:
	if (*objp) {
	     if((ret = krb5_unparse_name(context, *objp, &p)) != 0) 
		  return FALSE;
	}
	if(!xdr_nullstring(xdrs, &p))
	    return FALSE;
	if (p) free(p);
	break;
    case XDR_DECODE:
	if(!xdr_nullstring(xdrs, &p))
	    return FALSE;
	if (p) {
	     ret = krb5_parse_name(context, p, &pr);
	     if(ret != 0) 
		  return FALSE;
	     *objp = pr;
	     free(p);
	} else
	     *objp = NULL;
	break;
    case XDR_FREE:
	if(*objp != NULL) 
	    krb5_free_principal(context, *objp);
	break;
    }
    return TRUE;
}
Пример #2
0
static int cli_credentials_set_from_ccache(struct cli_credentials *cred, 
					   struct ccache_container *ccache,
					   enum credentials_obtained obtained,
					   const char **error_string)
{
	
	krb5_principal princ;
	krb5_error_code ret;
	char *name;

	if (cred->ccache_obtained > obtained) {
		return 0;
	}

	ret = krb5_cc_get_principal(ccache->smb_krb5_context->krb5_context, 
				    ccache->ccache, &princ);

	if (ret) {
		(*error_string) = talloc_asprintf(cred, "failed to get principal from ccache: %s\n",
						  smb_get_krb5_error_message(ccache->smb_krb5_context->krb5_context,
									     ret, cred));
		return ret;
	}
	
	ret = krb5_unparse_name(ccache->smb_krb5_context->krb5_context, princ, &name);
	if (ret) {
		(*error_string) = talloc_asprintf(cred, "failed to unparse principal from ccache: %s\n",
						  smb_get_krb5_error_message(ccache->smb_krb5_context->krb5_context,
									     ret, cred));
		return ret;
	}

	cli_credentials_set_principal(cred, name, obtained);

	free(name);

	krb5_free_principal(ccache->smb_krb5_context->krb5_context, princ);

	/* set the ccache_obtained here, as it just got set to UNINITIALISED by the calls above */
	cred->ccache_obtained = obtained;

	return 0;
}
Пример #3
0
static int
set_random_password (krb5_principal principal, int keepold)
{
    krb5_error_code ret;
    char pw[128];

    random_password (pw, sizeof(pw));
    ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL, pw);
    if (ret == 0) {
	char *princ_name;

	krb5_unparse_name(context, principal, &princ_name);

	printf ("%s's password set to \"%s\"\n", princ_name, pw);
	free (princ_name);
    }
    memset (pw, 0, sizeof(pw));
    return ret;
}
Пример #4
0
/*
 * initialize
 *
 * initialize the cache, check to see if one already exists for this
 * principal if not set our principal to this principal. This
 * searching enables ticket sharing
 */
krb5_error_code KRB5_CALLCONV  krb5_stdcc_initialize 
       (krb5_context context, krb5_ccache id,  krb5_principal princ) 
{
	stdccCacheDataPtr	ccapi_data = NULL;
  	int 			err;
  	char 			*cName = NULL;
	krb5_error_code		retval;
  	
	if ((retval = stdcc_setup(context, NULL)))
		return retval;
	
  	/* test id for null */
  	if (id == NULL) return KRB5_CC_NOMEM;
  	
	if ((retval = krb5_unparse_name(context, princ, &cName)))
		return retval;

	ccapi_data = id->data;


	if (ccapi_data->NamedCache)
		cc_close(gCntrlBlock, &ccapi_data->NamedCache);

	err = cc_create(gCntrlBlock, ccapi_data->cache_name, cName,
			CC_CRED_V5, 0L, &ccapi_data->NamedCache);
	if (err != CC_NOERROR) {
		krb5_free_unparsed_name(context, cName);
		return cc_err_xlate(err);
	}

#if 0
	/*
	 * Some implementations don't set the principal name
	 * correctly, so we force set it to the correct value.
	 */
	err = cc_set_principal(gCntrlBlock, ccapi_data->NamedCache,
			       CC_CRED_V5, cName);
#endif
	krb5_free_unparsed_name(context, cName);
	cache_changed();
	
	return cc_err_xlate(err);
}
Пример #5
0
krb5_error_code
krb5_check_transited_list (krb5_context ctx, const krb5_data *trans_in,
                           const krb5_data *crealm, const krb5_data *srealm)
{
    krb5_data trans;
    struct check_data cdata;
    krb5_error_code r;

    trans.length = trans_in->length;
    trans.data = (char *) trans_in->data;
    if (trans.length && (trans.data[trans.length-1] == '\0'))
        trans.length--;

    Tprintf (("krb5_check_transited_list(trans=\"%.*s\", crealm=\"%.*s\", srealm=\"%.*s\")\n",
              (int) trans.length, trans.data,
              (int) crealm->length, crealm->data,
              (int) srealm->length, srealm->data));
    if (trans.length == 0)
        return 0;
    r = krb5_walk_realm_tree (ctx, crealm, srealm, &cdata.tgs,
                              KRB5_REALM_BRANCH_CHAR);
    if (r) {
        Tprintf (("error %ld\n", (long) r));
        return r;
    }
#ifdef DEBUG /* avoid compiler warning about 'd' unused */
    {
        int i;
        Tprintf (("tgs list = {\n"));
        for (i = 0; cdata.tgs[i]; i++) {
            char *name;
            r = krb5_unparse_name (ctx, cdata.tgs[i], &name);
            Tprintf (("\t'%s'\n", name));
            free (name);
        }
        Tprintf (("}\n"));
    }
#endif
    cdata.ctx = ctx;
    r = foreach_realm (check_realm_in_list, &cdata, crealm, srealm, &trans);
    krb5_free_realm_tree (ctx, cdata.tgs);
    return r;
}
Пример #6
0
krb5_error_code KRB5_CALLCONV
krb5_cc_cache_match(krb5_context context, krb5_principal client,
                    krb5_ccache *cache_out)
{
    krb5_error_code ret;
    krb5_cccol_cursor cursor;
    krb5_ccache cache = NULL;
    krb5_principal princ;
    char *name;
    krb5_boolean eq;

    *cache_out = NULL;
    ret = krb5_cccol_cursor_new(context, &cursor);
    if (ret)
        return ret;

    while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 &&
           cache != NULL) {
        ret = krb5_cc_get_principal(context, cache, &princ);
        if (ret == 0) {
            eq = krb5_principal_compare(context, princ, client);
            krb5_free_principal(context, princ);
            if (eq)
                break;
        }
        krb5_cc_close(context, cache);
    }
    krb5_cccol_cursor_free(context, &cursor);
    if (ret)
        return ret;
    if (cache == NULL) {
        ret = krb5_unparse_name(context, client, &name);
        if (ret == 0) {
            k5_setmsg(context, KRB5_CC_NOTFOUND,
                      _("Can't find client principal %s in cache collection"),
                      name);
            krb5_free_unparsed_name(context, name);
        }
        ret = KRB5_CC_NOTFOUND;
    } else
        *cache_out = cache;
    return ret;
}
Пример #7
0
 krb5_error_code smb_krb5_unparse_name(krb5_context context,
					krb5_const_principal principal,
					char **unix_name)
{
	krb5_error_code ret;
	char *utf8_name;

	ret = krb5_unparse_name(context, principal, &utf8_name);
	if (ret) {
		return ret;
	}

	if (pull_utf8_allocate(unix_name, utf8_name)==-1) {
		krb5_free_unparsed_name(context, utf8_name);
		return ENOMEM;
	}
	krb5_free_unparsed_name(context, utf8_name);
	return 0;
}
Пример #8
0
jobject BuildClientPrincipal(JNIEnv *env, krb5_context kcontext, krb5_principal principalName) {
    // Get the full principal string.
    char *principalString = NULL;
    jobject principal = NULL;
    int err = krb5_unparse_name (kcontext, principalName, &principalString);

    if (!err) {
        // Make a PrincipalName from the full string and the type.  Let the PrincipalName class parse it out.
        jstring principalStringObj = (*env)->NewStringUTF(env, principalString);
        if (principalStringObj == NULL) {
            if (principalString != NULL) { krb5_free_unparsed_name (kcontext, principalString); }
            return (jobject) NULL;
        }
        principal = (*env)->NewObject(env, principalNameClass, principalNameConstructor, principalStringObj, principalName->type);
        if (principalString != NULL) { krb5_free_unparsed_name (kcontext, principalString); }
        (*env)->DeleteLocalRef(env, principalStringObj);
    }

    return principal;
}
Пример #9
0
/*
 * call-seq:
 *   get_default_principal -> string
 *
 * Call krb5_cc_get_principal() to get the principal from the default
 * cachefile.  Returns the default principal on success, raises a
 * Krb5Auth::Krb5::Exception on failure.
 */
static VALUE Krb5_get_default_principal(VALUE self)
{
  struct ruby_krb5 *kerb;
  char *princ_name;
  VALUE result;
  krb5_error_code krbret;
  krb5_ccache cc;

  Data_Get_Struct(self, struct ruby_krb5, kerb);
  if (!kerb) {
    NOSTRUCT_EXCEPT();
    return Qfalse;
  }

  krbret = krb5_cc_default(kerb->ctx, &cc);
  if (krbret) {
    Krb5_register_error(krbret);
    return Qfalse;
  }

  krbret = krb5_cc_get_principal(kerb->ctx, cc, &kerb->princ);
  if (krbret) {
    krb5_cc_close(kerb->ctx, cc);
    Krb5_register_error(krbret);    
    return Qnil;
  }

  krb5_cc_close(kerb->ctx, cc);

  krbret = krb5_unparse_name(kerb->ctx, kerb->princ, &princ_name);
  if (krbret) {
    Krb5_register_error(krbret);    
    return Qnil;
  }

  result = rb_str_new2(princ_name);

  free(princ_name);

  return result;
}
Пример #10
0
krb5_error_code
krb5_dbe_update_mod_princ_data(krb5_context context, krb5_db_entry *entry,
                               krb5_timestamp mod_date,
                               krb5_const_principal mod_princ)
{
    krb5_tl_data          tl_data;

    krb5_error_code       retval = 0;
    krb5_octet          * nextloc = 0;
    char                * unparse_mod_princ = 0;
    unsigned int        unparse_mod_princ_size;

    if ((retval = krb5_unparse_name(context, mod_princ,
                                    &unparse_mod_princ)))
        return(retval);

    unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;

    if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
        == NULL) {
        free(unparse_mod_princ);
        return(ENOMEM);
    }

    tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
    tl_data.tl_data_length = unparse_mod_princ_size + 4;
    tl_data.tl_data_contents = nextloc;

    /* Mod Date */
    krb5_kdb_encode_int32(mod_date, nextloc);

    /* Mod Princ */
    memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);

    retval = krb5_dbe_update_tl_data(context, entry, &tl_data);

    free(unparse_mod_princ);
    free(nextloc);

    return(retval);
}
Пример #11
0
static krb5_error_code
foreach(krb5_context context, HDB *db, hdb_entry_ex *ent, void *data)
{
    struct foreach_data *d = data;
    char *princ;
    krb5_error_code ret;
    ret = krb5_unparse_name(context, ent->entry.principal, &princ);
    if(ret)
	return ret;
    if(d->exp){
	if(fnmatch(d->exp, princ, 0) == 0 || fnmatch(d->exp2, princ, 0) == 0)
	    ret = add_princ(d, princ);
	else
	    free(princ);
    }else{
	ret = add_princ(d, princ);
    }
    if(ret)
	free(princ);
    return ret;
}
Пример #12
0
static int
do_check_entry(krb5_principal principal, void *data)
{
    krb5_error_code ret;
    kadm5_principal_ent_rec princ;
    char *name;
    int i;

    ret = krb5_unparse_name(context, principal, &name);
    if (ret)
	return 1;

    memset (&princ, 0, sizeof(princ));
    ret = kadm5_get_principal(kadm_handle, principal, &princ,
			      KADM5_PRINCIPAL | KADM5_KEY_DATA);
    if(ret) {
	krb5_warn(context, ret, "Failed to get principal: %s", name);
	free(name);
	return 0;
    }

    for (i = 0; i < princ.n_key_data; i++) {
	size_t keysize;
	ret = krb5_enctype_keysize(context,
				   princ.key_data[i].key_data_type[0],
				   &keysize);
	if (ret == 0 && keysize != princ.key_data[i].key_data_length[0]) {
	    krb5_warnx(context,
		       "Principal %s enctype %d, wrong length: %lu\n",
		       name, princ.key_data[i].key_data_type[0],
		       (unsigned long)princ.key_data[i].key_data_length);
	}
    }

    free(name);
    kadm5_free_principal_ent(kadm_handle, &princ);

    return 0;
}
Пример #13
0
void
test_425_conv_principal(krb5_context ctx, char *name, char *inst, char *realm)
{
    krb5_error_code     retval;
    krb5_principal      princ;
    char                *out_name;

    retval = krb5_425_conv_principal(ctx, name, inst, realm, &princ);
    if (retval) {
        com_err("krb5_425_conv_principal", retval, 0);
        return;
    }
    retval = krb5_unparse_name(ctx, princ, &out_name);
    if (retval) {
        com_err("krb5_unparse_name", retval, 0);
        return;
    }
    printf("425_converted principal(%s, %s, %s): '%s'\n",
           name, inst, realm, out_name);
    free(out_name);
    krb5_free_principal(ctx, princ);
}
Пример #14
0
/*
 * krb5_principal_size()	- Determine the size required to externalize
 *				  the krb5_principal.
 */
static krb5_error_code
krb5_principal_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
{
    krb5_error_code	kret;
    krb5_principal	principal;
    char		*fname;

    /*
     * krb5_principal requires:
     *	krb5_int32			for KV5M_PRINCIPAL
     *	krb5_int32			for flattened name size
     *	strlen(name)			for name.
     *	krb5_int32			for KV5M_PRINCIPAL
     */
    kret = EINVAL;
    if ((principal = (krb5_principal) arg) &&
	!(kret = krb5_unparse_name(kcontext, principal, &fname))) {
	*sizep += (3*sizeof(krb5_int32)) + strlen(fname);
	krb5_xfree(fname);
    }
    return(kret);
}
Пример #15
0
static void
test_alname(krb5_context context, krb5_const_realm realm,
	    const char *user, const char *inst, 
	    const char *localuser, int ok)
{
    krb5_principal p;
    char localname[1024];
    krb5_error_code ret;
    char *princ;

    ret = krb5_make_principal(context, &p, realm, user, inst, NULL);
    if (ret)
	krb5_err(context, 1, ret, "krb5_build_principal");

    ret = krb5_unparse_name(context, p, &princ);
    if (ret)
	krb5_err(context, 1, ret, "krb5_unparse_name");

    ret = krb5_aname_to_localname(context, p, sizeof(localname), localname);
    krb5_free_principal(context, p);
    free(princ);
    if (ret) {
	if (!ok)
	    return;
	krb5_err(context, 1, ret, "krb5_aname_to_localname: %s -> %s", 
		 princ, localuser);
    }

    if (strcmp(localname, localuser) != 0) {
	if (ok)
	    errx(1, "compared failed %s != %s (should have succeded)", 
		 localname, localuser);
    } else {
	if (!ok)
	    errx(1, "compared failed %s == %s (should have failed)", 
		 localname, localuser);
    }
    
}
Пример #16
0
Файл: 524.c Проект: gojdic/samba
static krb5_error_code
fetch_server (krb5_context context,
	      krb5_kdc_configuration *config,
	      const Ticket *t,
	      char **spn,
	      hdb_entry_ex **server,
	      const char *from)
{
    krb5_error_code ret;
    krb5_principal sprinc;

    ret = _krb5_principalname2krb5_principal(context, &sprinc,
					     t->sname, t->realm);
    if (ret) {
	kdc_log(context, config, 0, "_krb5_principalname2krb5_principal: %s",
		krb5_get_err_text(context, ret));
	return ret;
    }
    ret = krb5_unparse_name(context, sprinc, spn);
    if (ret) {
	krb5_free_principal(context, sprinc);
	kdc_log(context, config, 0, "krb5_unparse_name: %s",
		krb5_get_err_text(context, ret));
	return ret;
    }
    ret = _kdc_db_fetch(context, config, sprinc, HDB_F_GET_SERVER,
			NULL, server);
    krb5_free_principal(context, sprinc);
    if (ret) {
	kdc_log(context, config, 0,
	"Request to convert ticket from %s for unknown principal %s: %s",
		from, *spn, krb5_get_err_text(context, ret));
	if (ret == HDB_ERR_NOENTRY)
	    ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
	return ret;
    }
    return 0;
}
Пример #17
0
static void
test_cache_iter(krb5_context context, const char *type, int destroy)
{
    krb5_cc_cache_cursor cursor;
    krb5_error_code ret;
    krb5_ccache id;

    ret = krb5_cc_cache_get_first (context, type, &cursor);
    if (ret == KRB5_CC_NOSUPP)
	return;
    else if (ret)
	krb5_err(context, 1, ret, "krb5_cc_cache_get_first(%s)", type);


    while ((ret = krb5_cc_cache_next (context, cursor, &id)) == 0) {
	krb5_principal principal;
	char *name;

	if (debug_flag)
	    printf("name: %s\n", krb5_cc_get_name(context, id));
	ret = krb5_cc_get_principal(context, id, &principal);
	if (ret == 0) {
	    ret = krb5_unparse_name(context, principal, &name);
	    if (ret == 0) {
		if (debug_flag)
		    printf("\tprincipal: %s\n", name);
		free(name);
	    }
	    krb5_free_principal(context, principal);
	}
	if (destroy)
	    krb5_cc_destroy(context, id);
	else
	    krb5_cc_close(context, id);
    }

    krb5_cc_cache_end_seq_get(context, cursor);
}
Пример #18
0
krb5_error_code KRB5_CALLCONV
krb5_init_creds_set_keytab(krb5_context context,
                           krb5_init_creds_context ctx,
                           krb5_keytab keytab)
{
    krb5_enctype *etype_list;
    krb5_error_code ret;
    char *name;

    ctx->gak_fct = get_as_key_keytab;
    ctx->gak_data = keytab;

    ret = lookup_etypes_for_keytab(context, keytab, ctx->request->client,
                                   &etype_list);
    if (ret) {
        TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(context, ret);
        return 0;
    }
    TRACE_INIT_CREDS_KEYTAB_LOOKUP(context, etype_list);

    /* Error out if we have no keys for the client principal. */
    if (etype_list == NULL) {
        ret = krb5_unparse_name(context, ctx->request->client, &name);
        if (ret == 0) {
            krb5_set_error_message(context, KRB5_KT_NOTFOUND,
                                   _("Keytab contains no suitable keys for "
                                     "%s"), name);
        }
        krb5_free_unparsed_name(context, name);
        return KRB5_KT_NOTFOUND;
    }

    /* Sort the request enctypes so the ones in the keytab appear first. */
    ret = sort_enctypes(ctx->request->ktype, ctx->request->nktypes,
                        etype_list);
    free(etype_list);
    return ret;
}
Пример #19
0
static krb5_error_code
LDAP_principal2message(krb5_context context, HDB * db,
		       krb5_principal princ, LDAPMessage ** msg)
{
    char *name, *name_short = NULL;
    krb5_error_code ret;
    krb5_realm *r, *r0;

    *msg = NULL;

    ret = krb5_unparse_name(context, princ, &name);
    if (ret)
	return ret;

    ret = krb5_get_default_realms(context, &r0);
    if(ret) {
	free(name);
	return ret;
    }
    for (r = r0; *r != NULL; r++) {
	if(strcmp(krb5_principal_get_realm(context, princ), *r) == 0) {
	    ret = krb5_unparse_name_short(context, princ, &name_short);
	    if (ret) {
		krb5_free_host_realm(context, r0);
		free(name);
		return ret;
	    }
	    break;
	}
    }
    krb5_free_host_realm(context, r0);

    ret = LDAP__lookup_princ(context, db, name, name_short, msg);
    free(name);
    free(name_short);

    return ret;
}
Пример #20
0
/*
 *
 * Function: Reads the name and realm out of the ccache.
 *
 * Parameters:
 *  ccache - credentials cache to get info from
 *
 *  name - buffer to hold user name
 *
 *  realm - buffer to hold the realm
 *
 *
 * Returns: TRUE if read names, FALSE if not
 *
 */
int
k5_name_from_ccache(krb5_ccache k5_ccache)
{
  krb5_error_code code;
  krb5_principal princ;
  char name[ANAME_SZ];
  char realm[REALM_SZ];
  char *defname;

  if (code = krb5_cc_get_principal(k5_context, k5_ccache, &princ))
    return FALSE;

  code = krb5_unparse_name(k5_context, princ, &defname);
  if (code) {
    return FALSE;
  }

  k5_kname_parse(name, realm, defname);       /* Extract the components */
  strcpy(cns_res.name, name);
  strcpy(cns_res.realm, realm);

  return TRUE;
}
Пример #21
0
kim_error kim_identity_get_string (kim_identity   in_identity,
                                   kim_string    *out_string)
{
    kim_error err = KIM_NO_ERROR;
    char *unparsed_name = NULL;

    if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
    if (!err && !out_string ) { err = check_error (KIM_NULL_PARAMETER_ERR); }

    if (!err) {
        err = krb5_error (in_identity->context,
                          krb5_unparse_name (in_identity->context,
                                             in_identity->principal,
                                             &unparsed_name));
    }

    if (!err) {
        err = kim_string_copy (out_string, unparsed_name);
    }

    if (unparsed_name) { krb5_free_unparsed_name (in_identity->context, unparsed_name); }

    return check_error (err);
}
Пример #22
0
static krb5_error_code
bind_principal(krb5_context context,
	       sqlite3 *db,
	       sqlite3_stmt *stmt,
	       int col,
	       krb5_const_principal principal)
{
    krb5_error_code ret;
    char *str;

    ret = krb5_unparse_name(context, principal, &str);
    if (ret)
	return ret;

    ret = sqlite3_bind_text(stmt, col, str, -1, free_krb5);
    if (ret != SQLITE_OK) {
	krb5_xfree(str);
	krb5_set_error_message(context, ENOMEM,
			       N_("scache bind principal: %s", ""),
			       sqlite3_errmsg(db));
	return ENOMEM;
    }
    return 0;
}
Пример #23
0
OM_uint32 gss_display_name
           (OM_uint32 * minor_status,
            const gss_name_t input_name,
            gss_buffer_t output_name_buffer,
            gss_OID * output_name_type
           )
{
    krb5_error_code kret;
    char *buf;
    size_t len;

    GSSAPI_KRB5_INIT ();
    kret = krb5_unparse_name (gssapi_krb5_context,
			      input_name,
			      &buf);
    if (kret) {
	*minor_status = kret;
	gssapi_krb5_set_error_string ();
	return GSS_S_FAILURE;
    }
    len = strlen (buf);
    output_name_buffer->length = len;
    output_name_buffer->value  = malloc(len + 1);
    if (output_name_buffer->value == NULL) {
	free (buf);
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }
    memcpy (output_name_buffer->value, buf, len);
    ((char *)output_name_buffer->value)[len] = '\0';
    free (buf);
    if (output_name_type)
	*output_name_type = GSS_KRB5_NT_PRINCIPAL_NAME;
    *minor_status = 0;
    return GSS_S_COMPLETE;
}
Пример #24
0
static const char* KRB5_CALLCONV
acc_get_name(krb5_context context,
	     krb5_ccache id)
{
    krb5_acc *a = ACACHE(id);
    int32_t error;

    if (a->cache_name == NULL) {
	krb5_error_code ret;
	krb5_principal principal;
	char *name;

	ret = _krb5_get_default_principal_local(context, &principal);
	if (ret)
	    return NULL;

	ret = krb5_unparse_name(context, principal, &name);
	krb5_free_principal(context, principal);
	if (ret)
	    return NULL;

	error = (*a->context->func->create_new_ccache)(a->context,
						       cc_credentials_v5,
						       name,
						       &a->ccache);
	krb5_xfree(name);
	if (error)
	    return NULL;

	error = get_cc_name(a);
	if (error)
	    return NULL;
    }

    return a->cache_name;
}
Пример #25
0
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_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 = NULL;
    krb5_init_creds_context ctx = NULL;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_prompter_fct prompter = krb5_prompter_posix;
#ifndef NO_NTLM
    struct ntlm_buf ntlmkey;
    memset(&ntlmkey, 0, sizeof(ntlmkey));
#endif
    passwd[0] = '\0';

    if (!interactive)
	prompter = NULL;

    if (password_file) {
	FILE *f;

	if (strcasecmp("STDIN", password_file) == 0)
	    f = stdin;
	else
	    f = fopen(password_file, "r");
	if (f == NULL) {
	    krb5_warnx(context, "Failed to open the password file %s",
		       password_file);
	    return errno;
	}

	if (fgets(passwd, sizeof(passwd), f) == NULL) {
	    krb5_warnx(context, N_("Failed to read password from file %s", ""),
		       password_file);
	    fclose(f);
	    return EINVAL; /* XXX Need a better error */
	}
	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_warn(context, ret, "krb5_get_init_creds_opt_alloc");
	goto out;
    }

    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,
						 prompter,
						 NULL,
						 passwd);
	if (ret) {
	    krb5_warn(context, ret, "krb5_get_init_creds_opt_set_pkinit");
	    goto out;
	}
	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, prompter, NULL, start_time, opt, &ctx);
    if (ret) {
	krb5_warn(context, ret, "krb5_init_creds_init");
	goto out;
    }

    if (server_str) {
	ret = krb5_init_creds_set_service(context, ctx, server_str);
	if (ret) {
	    krb5_warn(context, ret, "krb5_init_creds_set_service");
	    goto out;
	}
    }

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

    if (use_keytab || keytab_str) {
	ret = krb5_init_creds_set_keytab(context, ctx, kt);
	if (ret) {
	    krb5_warn(context, ret, "krb5_init_creds_set_keytab");
	    goto out;
	}
    } else if (pk_user_id || ent_user_id || anonymous_flag) {

    } else if (!interactive && passwd[0] == '\0') {
	static int already_warned = 0;

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

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

	    ret = krb5_unparse_name(context, principal, &p);
	    if (ret)
		errx(1, "failed to generate passwd prompt: not enough memory");

	    aret = asprintf(&prompt, N_("%s's Password: "******""), p);
	    free(p);
	    if (aret == -1)
		errx(1, "failed to generate passwd prompt: not enough memory");

	    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_warn(context, ret, "krb5_init_creds_set_password");
		goto out;
	    }
	}
    }

    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:
    case KRB5_GET_IN_TKT_LOOP:
	krb5_warnx(context, N_("Password incorrect", ""));
	goto out;
    case KRB5KRB_AP_ERR_V4_REPLY:
	krb5_warnx(context, N_("Looks like a Kerberos 4 reply", ""));
	goto out;
    case KRB5KDC_ERR_KEY_EXPIRED:
	krb5_warnx(context, N_("Password expired", ""));
	goto out;
    default:
	krb5_warn(context, ret, "krb5_get_init_creds");
	goto out;
    }

    krb5_process_last_request(context, opt, ctx);

    ret = krb5_init_creds_get_creds(context, ctx, &cred);
    if (ret) {
	krb5_warn(context, ret, "krb5_init_creds_get_creds");
	goto out;
    }

    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);
	}
    }
    krb5_free_cred_contents(context, &cred);

    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache),
			     NULL, &tempccache);
    if (ret) {
	krb5_warn(context, ret, "krb5_cc_new_unique");
	goto out;
    }

    ret = krb5_init_creds_store(context, ctx, tempccache);
    if (ret) {
	krb5_warn(context, ret, "krb5_init_creds_store");
	goto out;
    }

    krb5_init_creds_free(context, ctx);
    ctx = NULL;

    ret = krb5_cc_move(context, tempccache, ccache);
    if (ret) {
	krb5_warn(context, ret, "krb5_cc_move");
	goto out;
    }
    tempccache = NULL;

    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);
    }

out:
    krb5_get_init_creds_opt_free(context, opt);
    if (ctx)
	krb5_init_creds_free(context, ctx);
    if (tempccache)
	krb5_cc_close(context, tempccache);

    if (enctype)
	free(enctype);

    return ret;
}
Пример #26
0
static int
kinit_check_tgt(kinit_data *kid, int *remaining)
{
	int ret=3;
	krb5_principal princ;
	krb5_error_code rc;
	krb5_cc_cursor cursor;
	krb5_creds creds;
	char *name;
	time_t now=time(NULL);

	rc = krb5_cc_get_principal(kid->ctx, kid->ccache, &princ);
	if (rc) {
		log_krb5_errmsg(kid->ctx, "krb5_cc_get_principal", rc);
		return 2;
	} else {
		if (!krb5_principal_compare(kid->ctx, kid->princ, princ)) {
			Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
					"Principal in ccache does not match requested principal\n");
			krb5_free_principal(kid->ctx, princ);
			return 2;
		}
	}

	rc = krb5_cc_start_seq_get(kid->ctx, kid->ccache, &cursor);
	if (rc) {
		log_krb5_errmsg(kid->ctx, "krb5_cc_start_seq_get", rc);
		krb5_free_principal(kid->ctx, princ);
		return -1;
	}

	while (!(rc = krb5_cc_next_cred(kid->ctx, kid->ccache, &cursor, &creds))) {
		if (krb5_is_config_principal(kid->ctx, creds.server)) {
			krb5_free_cred_contents(kid->ctx, &creds);
			continue;
		}

		if (creds.server->length==2 &&
				(!strcmp(creds.server->data[0].data, "krbtgt")) &&
				(!strcmp(creds.server->data[1].data, princ->realm.data))) {

			krb5_unparse_name(kid->ctx, creds.server, &name);

			*remaining = (time_t)creds.times.endtime-now;
			if ( *remaining <= 0) {
				Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
						"kinit_qtask: TGT (%s) expired\n", name);
			} else {
				Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
						"kinit_qtask: TGT (%s) expires in %dh:%02dm:%02ds\n",
						name, *remaining/3600, (*remaining%3600)/60, *remaining%60);
			}
			free(name);

			if (*remaining <= 30) {
				if (creds.times.renew_till-60 > now) {
					int renewal=creds.times.renew_till-now;
					Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
							"kinit_qtask: Time remaining for renewal: %dh:%02dm:%02ds\n",
							renewal/3600, (renewal%3600)/60,  renewal%60);
					ret = 1;
				} else {
					Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
							"kinit_qtask: Only short time left for renewal. "
							"Trying to re-init.\n");
					ret = 2;
				}
			} else {
				ret=0;
			}
			krb5_free_cred_contents(kid->ctx, &creds);
			break;
		}
		krb5_free_cred_contents(kid->ctx, &creds);

	}
	krb5_cc_end_seq_get(kid->ctx, kid->ccache, &cursor);
	krb5_free_principal(kid->ctx, princ);
	return ret;
}
Пример #27
0
int print_keytab (const char *in_name)
{
    krb5_error_code err = 0;
    krb5_keytab kt;
    krb5_keytab_entry entry;
    krb5_kt_cursor cursor;
    char keytab_name[BUFSIZ]; /* hopefully large enough for any type */

    if (!err) {
        if (!in_name) {
            err = krb5_kt_default (kcontext, &kt);
            printiferr (err, "while resolving default keytab");
        } else {
            err = krb5_kt_resolve (kcontext, in_name, &kt);
            printiferr (err, "while resolving keytab %s", in_name);
        }
    }

    if (!err) {
        err = krb5_kt_get_name (kcontext, kt, keytab_name, sizeof (keytab_name));
        printiferr (err, "while getting keytab name");
    }

    if (!err) {
        printmsg ("Keytab name: %s\n", keytab_name);
    }

    if (!err) {
        err = krb5_kt_start_seq_get (kcontext, kt, &cursor);
        printiferr (err, "while starting scan of keytab %s", keytab_name);
    }

    if (!err) {
        if (show_entry_timestamps) {
            printmsg ("KVNO Timestamp");
            printfiller (' ', get_timestamp_width () - sizeof ("Timestamp") + 2);
            printmsg ("Principal\n");
            printmsg ("---- ");
            printfiller ('-', get_timestamp_width ());
            printmsg (" ");
            printfiller ('-', 78 - get_timestamp_width () - sizeof ("KVNO"));
            printmsg ("\n");
        } else {
            printmsg("KVNO Principal\n");
            printmsg("---- --------------------------------------------------------------------------\n");
        }
    }

    while (!err) {
        char *principal_name = NULL;

        err = krb5_kt_next_entry (kcontext, kt, &entry, &cursor);
	if (err == KRB5_KT_END) {
	    err = 0;
	    break;
	}
 
        if (!err) {
            err = krb5_unparse_name (kcontext, entry.principal, &principal_name);
            printiferr (err, "while unparsing principal name");
        }
        
        if (!err) {
            printmsg ("%4d ", entry.vno);
            if (show_entry_timestamps) {
                printtime (entry.timestamp);
                printmsg (" ");
            }
            printmsg ("%s", principal_name);
            if (show_enctypes) {
                printmsg (" (%s) ", enctype_to_string (entry.key.enctype));
            }
            if (show_entry_DES_keys) {
                unsigned int i;
                
                printmsg (" (0x");
                for (i = 0; i < entry.key.length; i++) {
                    printmsg ("%02x", entry.key.contents[i]);
                }
                printmsg (")");
            }
            printmsg ("\n");
        }
	printiferr (err, "while scanning keytab %s", keytab_name);

        if (principal_name) { krb5_free_unparsed_name (kcontext, principal_name); }
    }

    if (!err) {
        err = krb5_kt_end_seq_get (kcontext, kt, &cursor);
        printiferr (err, "while ending scan of keytab %s", keytab_name);
    }

    return err ? 1 : 0;
}
Пример #28
0
static krb5_error_code
krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
			const krb5_ap_req *req, krb5_const_principal server,
			krb5_keytab keytab, krb5_flags *ap_req_options,
			krb5_ticket **ticket, int check_valid_flag)
{
    krb5_error_code 	  retval = 0;
    krb5_timestamp 	  currenttime;
    krb5_principal_data princ_data;
    
    req->ticket->enc_part2 == NULL;
    if (server && krb5_is_referral_realm(&server->realm)) {
	char *realm;
	princ_data = *server;
	server = &princ_data;
	retval = krb5_get_default_realm(context, &realm);
	if (retval)
	    return retval;
	princ_data.realm.data = realm;
	princ_data.realm.length = strlen(realm);
    }
    if (server && !krb5_principal_compare(context, server, req->ticket->server)) {
	char *found_name = 0, *wanted_name = 0;
	if (krb5_unparse_name(context, server, &wanted_name) == 0
	    && krb5_unparse_name(context, req->ticket->server, &found_name) == 0)
	    krb5_set_error_message(context, KRB5KRB_AP_WRONG_PRINC,
				   "Wrong principal in request (found %s, wanted %s)",
				   found_name, wanted_name);
	krb5_free_unparsed_name(context, wanted_name);
	krb5_free_unparsed_name(context, found_name);
	retval =  KRB5KRB_AP_WRONG_PRINC;
	goto cleanup;
    }

    /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
       do we need special processing here ?	*/

    /* decrypt the ticket */
    if ((*auth_context)->keyblock) { /* User to User authentication */
    	if ((retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock,
					    req->ticket)))
goto cleanup;
	krb5_free_keyblock(context, (*auth_context)->keyblock);
	(*auth_context)->keyblock = NULL;
    } else {
    	if ((retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab)))
	    goto cleanup;
    }

    /* XXX this is an evil hack.  check_valid_flag is set iff the call
       is not from inside the kdc.  we can use this to determine which
       key usage to use */
    if ((retval = decrypt_authenticator(context, req, 
					&((*auth_context)->authentp),
					check_valid_flag)))
	goto cleanup;

    if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
				req->ticket->enc_part2->client)) {
	retval = KRB5KRB_AP_ERR_BADMATCH;
	goto cleanup;
    }

    if ((*auth_context)->remote_addr && 
      !krb5_address_search(context, (*auth_context)->remote_addr, 
			   req->ticket->enc_part2->caddrs)) {
	retval = KRB5KRB_AP_ERR_BADADDR;
	goto cleanup;
    }

    /* okay, now check cross-realm policy */

#if defined(_SINGLE_HOP_ONLY)

    /* Single hop cross-realm tickets only */

    { 
	krb5_transited *trans = &(req->ticket->enc_part2->transited);

      	/* If the transited list is empty, then we have at most one hop */
      	if (trans->tr_contents.data && trans->tr_contents.data[0])
            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
    }

#elif defined(_NO_CROSS_REALM)

    /* No cross-realm tickets */

    { 
	char		* lrealm;
      	krb5_data      	* realm;
      	krb5_transited 	* trans;
  
	realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
	trans = &(req->ticket->enc_part2->transited);

	/*
      	 * If the transited list is empty, then we have at most one hop 
      	 * So we also have to check that the client's realm is the local one 
	 */
      	krb5_get_default_realm(context, &lrealm);
      	if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
          strlen(lrealm) != realm->length ||
          memcmp(lrealm, realm->data, strlen(lrealm))) {
            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
      	}
      	free(lrealm);
    }

#else

    /* Hierarchical Cross-Realm */
  
    {
      	krb5_data      * realm;
      	krb5_transited * trans;
  
	realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
	trans = &(req->ticket->enc_part2->transited);

	/*
      	 * If the transited list is not empty, then check that all realms 
      	 * transited are within the hierarchy between the client's realm  
      	 * and the local realm.                                        
  	 */
	if (trans->tr_contents.data && trans->tr_contents.data[0]) {
	    retval = krb5_check_transited_list(context, &(trans->tr_contents), 
					       realm,
					       krb5_princ_realm (context,
								 server));
      	}
    }

#endif

    if (retval)  goto cleanup;

    /* only check rcache if sender has provided one---some services
       may not be able to use replay caches (such as datagram servers) */

    if ((*auth_context)->rcache) {
	krb5_donot_replay  rep;
        krb5_tkt_authent   tktauthent;

	tktauthent.ticket = req->ticket;	
	tktauthent.authenticator = (*auth_context)->authentp;
	if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) {
	    retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
	    krb5_xfree(rep.server);
	    krb5_xfree(rep.client);
	}

	if (retval)
	    goto cleanup;
    }

    retval = krb5_validate_times(context, &req->ticket->enc_part2->times);
    if (retval != 0)
	    goto cleanup;

    if ((retval = krb5_timeofday(context, &currenttime)))
	goto cleanup;

    if (!in_clock_skew((*auth_context)->authentp->ctime)) {
	retval = KRB5KRB_AP_ERR_SKEW;
	goto cleanup;
    }

    if (check_valid_flag) {
      if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) {
	retval = KRB5KRB_AP_ERR_TKT_INVALID;
	goto cleanup;
      }
    }

    /* check if the various etypes are permitted */

    if ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) {
	/* no etype check needed */;
    } else if ((*auth_context)->permitted_etypes == NULL) {
	int etype;
	/* check against the default set */
	if ((!krb5_is_permitted_enctype(context,
					etype = req->ticket->enc_part.enctype)) ||
	    (!krb5_is_permitted_enctype(context,
					etype = req->ticket->enc_part2->session->enctype)) ||
	    (((*auth_context)->authentp->subkey) &&
	     !krb5_is_permitted_enctype(context,
					etype = (*auth_context)->authentp->subkey->enctype))) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
    } else {
	/* check against the set in the auth_context */
	int i;

	for (i=0; (*auth_context)->permitted_etypes[i]; i++)
	    if ((*auth_context)->permitted_etypes[i] ==
		req->ticket->enc_part.enctype)
		break;
	if (!(*auth_context)->permitted_etypes[i]) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(req->ticket->enc_part.enctype,
				       enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
	
	for (i=0; (*auth_context)->permitted_etypes[i]; i++)
	    if ((*auth_context)->permitted_etypes[i] ==
		req->ticket->enc_part2->session->enctype)
		break;
	if (!(*auth_context)->permitted_etypes[i]) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(req->ticket->enc_part2->session->enctype,
				       enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
	
	if ((*auth_context)->authentp->subkey) {
	    for (i=0; (*auth_context)->permitted_etypes[i]; i++)
		if ((*auth_context)->permitted_etypes[i] ==
		    (*auth_context)->authentp->subkey->enctype)
		    break;
	    if (!(*auth_context)->permitted_etypes[i]) {
		char enctype_name[30];
		retval = KRB5_NOPERM_ETYPE;
		if (krb5_enctype_to_string((*auth_context)->authentp->subkey->enctype,
					   enctype_name,
					   sizeof(enctype_name)) == 0)
		    krb5_set_error_message(context, retval,
					   "Encryption type %s not permitted",
					   enctype_name);
		goto cleanup;
	    }
	}
    }

    (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number;
    if ((*auth_context)->authentp->subkey) {
	if ((retval = krb5_copy_keyblock(context,
					 (*auth_context)->authentp->subkey,
					 &((*auth_context)->recv_subkey))))
	    goto cleanup;
	retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey,
				    &((*auth_context)->send_subkey));
	if (retval) {
	    krb5_free_keyblock(context, (*auth_context)->recv_subkey);
	    (*auth_context)->recv_subkey = NULL;
	    goto cleanup;
	}
    } else {
	(*auth_context)->recv_subkey = 0;
	(*auth_context)->send_subkey = 0;
    }

    if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session,
				     &((*auth_context)->keyblock))))
	goto cleanup;

    /*
     * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used 
     * then the default sequence number is the one's complement of the
     * sequence number sent ot us.
     */
    if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && 
      (*auth_context)->remote_seq_number) {
	(*auth_context)->local_seq_number ^= 
	  (*auth_context)->remote_seq_number;
    }

    if (ticket)
   	if ((retval = krb5_copy_ticket(context, req->ticket, ticket)))
	    goto cleanup;
    if (ap_req_options)
    	*ap_req_options = req->ap_options;
    retval = 0;
    
cleanup:
    if (server == &princ_data)
	krb5_free_default_realm(context, princ_data.realm.data);
    if (retval) {
	/* only free if we're erroring out...otherwise some
	   applications will need the output. */
	if (req->ticket->enc_part2)
	    krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
	req->ticket->enc_part2 = NULL;
    }
    return retval;
}
Пример #29
0
/* Get a TGT for use at the remote host */
krb5_error_code KRB5_CALLCONV
krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf)
                         
                                   
                
                          
                          
                   
                          /* Should forwarded TGT also be forwardable? */
                      
{
    krb5_replay_data replaydata;
    krb5_data * scratch = 0;
    krb5_address **addrs = NULL;
    krb5_error_code retval;
    krb5_creds creds, tgt;
    krb5_creds *pcreds;
    krb5_flags kdcoptions;
    int close_cc = 0;
    int free_rhost = 0;
    krb5_enctype enctype = 0;
    krb5_keyblock *session_key;
    krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes;

    memset((char *)&creds, 0, sizeof(creds));
    memset((char *)&tgt, 0, sizeof(creds));

    if (cc == 0) {
      if ((retval = krb5int_cc_default(context, &cc)))
	goto errout;
      close_cc = 1;
    }
    retval = krb5_auth_con_getkey (context, auth_context, &session_key);
    if (retval)
      goto errout;
    if (session_key) {
	enctype = session_key->enctype;
	krb5_free_keyblock (context, session_key);
	session_key = NULL;
    } else if (server) { /* must server be non-NULL when rhost is given? */
	/* Try getting credentials to see what the remote side supports.
	   Not bulletproof, just a heuristic.  */
	krb5_creds in, *out = 0;
	memset (&in, 0, sizeof(in));

	retval = krb5_copy_principal (context, server, &in.server);
	if (retval)
	    goto punt;
	retval = krb5_copy_principal (context, client, &in.client);
	if (retval)
	    goto punt;
	retval = krb5_get_credentials (context, 0, cc, &in, &out);
	if (retval)
	    goto punt;
	/* Got the credentials.  Okay, now record the enctype and
	   throw them away.  */
	enctype = out->keyblock.enctype;
	krb5_free_creds (context, out);
    punt:
	krb5_free_cred_contents (context, &in);
    }

    if ((retval = krb5_copy_principal(context, client, &creds.client)))
	goto errout;
    
    if ((retval = krb5_build_principal_ext(context, &creds.server,
					   client->realm.length,
					   client->realm.data,
					   KRB5_TGS_NAME_SIZE,
					   KRB5_TGS_NAME,
					   client->realm.length,
					   client->realm.data,
					   0)))
	goto errout;
	
    /* fetch tgt directly from cache */
    context->use_conf_ktypes = 1;
    retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES,
				    &creds, &tgt);
    context->use_conf_ktypes = old_use_conf_ktypes;
    if (retval)
	goto errout;

    /* tgt->client must be equal to creds.client */
    if (!krb5_principal_compare(context, tgt.client, creds.client)) {	
        /* Solaris Kerberos */
        char *r_name = NULL;
	char *t_name = NULL;
	krb5_error_code r_err, t_err;
	t_err = krb5_unparse_name(context, tgt.client, &t_name);
	r_err = krb5_unparse_name(context, creds.client, &r_name);
	krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
			    dgettext(TEXT_DOMAIN,
				    "Requested principal and ticket don't match:  Requested principal is '%s' and TGT principal is '%s'"),
			    r_err ? "unknown" : r_name,
			    t_err ? "unknown" : t_name);
	if (r_name)
	    krb5_free_unparsed_name(context, r_name);
	if (t_name)
	    krb5_free_unparsed_name(context, t_name);
	retval = KRB5_PRINC_NOMATCH;
	goto errout;
    }

    if (!tgt.ticket.length) {
	retval = KRB5_NO_TKT_SUPPLIED;
	goto errout;
    }
    
    if (tgt.addresses && *tgt.addresses) {
      if (rhost == NULL) {
	if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
retval = KRB5_FWD_BAD_PRINCIPAL;
 goto errout;
	}

	if (krb5_princ_size(context, server) < 2){
	  retval = KRB5_CC_BADNAME;
	  goto errout;
	}
	
	rhost = malloc(server->data[1].length+1);
	if (!rhost) {
	  retval = ENOMEM;
	  goto errout;
	}
	free_rhost = 1;
	/* Solaris Kerberos */
	(void) memcpy(rhost, server->data[1].data, server->data[1].length);
	rhost[server->data[1].length] = '\0';
      }

	retval = krb5_os_hostaddr(context, rhost, &addrs);
	if (retval)
	    goto errout;
    }
    
    creds.keyblock.enctype = enctype;
    creds.times = tgt.times;
    creds.times.starttime = 0;
    kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;

    if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
      kdcoptions &= ~(KDC_OPT_FORWARDABLE);

    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
					addrs, &creds, &pcreds))) {
	if (enctype) {
	    creds.keyblock.enctype = 0;
	    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
						addrs, &creds, &pcreds))) 
		goto errout;
	}
	else goto errout;
    }
    retval = krb5_mk_1cred(context, auth_context, pcreds,
                           &scratch, &replaydata);
    krb5_free_creds(context, pcreds);

    /*
     * Solaris Kerberos: changed this logic from the MIT 1.2.1 version to be
     * more robust.
     */
    if (scratch) {
	if (retval)
	    krb5_free_data(context, scratch);
	else {                                 
	    *outbuf = *scratch;
	    krb5_xfree(scratch);
	}                      
    }
        
errout:
    if (addrs)
	krb5_free_addresses(context, addrs);
    /* Solaris Kerberos */
    if (close_cc)
	(void) krb5_cc_close(context, cc);
    if (free_rhost)
	free(rhost);
    krb5_free_cred_contents(context, &creds);
    krb5_free_cred_contents(context, &tgt);
    return retval;
}
Пример #30
0
static krb5_error_code
verify_client_san(krb5_context context,
		  pkinit_kdc_context plgctx,
		  pkinit_kdc_req_context reqctx,
		  krb5_principal client,
		  int *valid_san)
{
    krb5_error_code retval;
    krb5_principal *princs = NULL;
    krb5_principal *upns = NULL;
    int i;
#ifdef DEBUG_SAN_INFO
    char *client_string = NULL, *san_string;
#endif
    
    retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx,
				       reqctx->cryptoctx, plgctx->idctx,
				       &princs,
				       plgctx->opts->allow_upn ? &upns : NULL,
				       NULL);
    if (retval) {
	pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
	goto out;
    }
    /* XXX Verify this is consistent with client side XXX */
#if 0
    retval = call_san_checking_plugins(context, plgctx, reqctx, princs,
				       upns, NULL, &plugin_decision, &ignore);
    pkiDebug("%s: call_san_checking_plugins() returned retval %d\n",
	     __FUNCTION__);
    if (retval) {
	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
	goto cleanup;
    }
    pkiDebug("%s: call_san_checking_plugins() returned decision %d\n",
	     __FUNCTION__, plugin_decision);
    if (plugin_decision != NO_DECISION) {
	retval = plugin_decision;
	goto out;
    }
#endif

#ifdef DEBUG_SAN_INFO
    krb5_unparse_name(context, client, &client_string);
#endif
    pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__);
    for (i = 0; princs != NULL && princs[i] != NULL; i++) {
#ifdef DEBUG_SAN_INFO
	krb5_unparse_name(context, princs[i], &san_string);
	pkiDebug("%s: Comparing client '%s' to pkinit san value '%s'\n",
		 __FUNCTION__, client_string, san_string);
	krb5_free_unparsed_name(context, san_string);
#endif
	if (krb5_principal_compare(context, princs[i], client)) {
	    pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
	    *valid_san = 1;
	    retval = 0;
	    goto out;
	}
    }
    pkiDebug("%s: no pkinit san match found\n", __FUNCTION__);
    /*
     * XXX if cert has names but none match, should we
     * be returning KRB5KDC_ERR_CLIENT_NAME_MISMATCH here?
     */

    if (upns == NULL) {
	pkiDebug("%s: no upn sans (or we wouldn't accept them anyway)\n",
		 __FUNCTION__);
	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
	goto out;
    }

    pkiDebug("%s: Checking upn sans\n", __FUNCTION__);
    for (i = 0; upns[i] != NULL; i++) {
#ifdef DEBUG_SAN_INFO
	krb5_unparse_name(context, upns[i], &san_string);
	pkiDebug("%s: Comparing client '%s' to upn san value '%s'\n",
		 __FUNCTION__, client_string, san_string);
	krb5_free_unparsed_name(context, san_string);
#endif
	if (krb5_principal_compare(context, upns[i], client)) {
	    pkiDebug("%s: upn san match found\n", __FUNCTION__);
	    *valid_san = 1;
	    retval = 0;
	    goto out;
	}
    }
    pkiDebug("%s: no upn san match found\n", __FUNCTION__);

    /* We found no match */
    if (princs != NULL || upns != NULL) {
	*valid_san = 0;
	/* XXX ??? If there was one or more name in the cert, but
	 * none matched the client name, then return mismatch? */
	retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
    }
    retval = 0;

out:
    if (princs != NULL) {
	for (i = 0; princs[i] != NULL; i++)
	    krb5_free_principal(context, princs[i]);
	free(princs);
    }
    if (upns != NULL) {
	for (i = 0; upns[i] != NULL; i++)
	    krb5_free_principal(context, upns[i]);
	free(upns);
    }
#ifdef DEBUG_SAN_INFO
    if (client_string != NULL)
	krb5_free_unparsed_name(context, client_string);
#endif
    pkiDebug("%s: returning retval %d, valid_san %d\n",
	     __FUNCTION__, retval, *valid_san);
    return retval;
}