コード例 #1
0
ファイル: import_name.c プロジェクト: 2asoft/freebsd
OM_uint32
_gsskrb5_canon_name(OM_uint32 *minor_status, krb5_context context,
		    int use_dns, krb5_const_principal sourcename, gss_name_t targetname,
		    krb5_principal *out)
{
    krb5_principal p = (krb5_principal)targetname;
    krb5_error_code ret;
    char *hostname = NULL, *service;

    *minor_status = 0;

    /* If its not a hostname */
    if (krb5_principal_get_type(context, p) != MAGIC_HOSTBASED_NAME_TYPE) {
	ret = krb5_copy_principal(context, p, out);
    } else if (!use_dns) {
	ret = krb5_copy_principal(context, p, out);
	if (ret)
	    goto out;
	krb5_principal_set_type(context, *out, KRB5_NT_SRV_HST);
	if (sourcename)
	    ret = krb5_principal_set_realm(context, *out, sourcename->realm);
    } else {
	if (p->name.name_string.len == 0)
	    return GSS_S_BAD_NAME;
	else if (p->name.name_string.len > 1)
	    hostname = p->name.name_string.val[1];

	service = p->name.name_string.val[0];

	ret = krb5_sname_to_principal(context,
				      hostname,
				      service,
				      KRB5_NT_SRV_HST,
				      out);
    }

 out:
    if (ret) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    return 0;
}
コード例 #2
0
ファイル: import_name.c プロジェクト: aosm/Heimdal
static OM_uint32
import_uuid_name(OM_uint32 *minor_status,
		 gss_const_OID mech,
		 const gss_buffer_t input_name_buffer,
		 gss_const_OID input_name_type,
		 gss_name_t *output_name)
{
    krb5_context context;
    krb5_error_code ret;
    krb5_principal princ;
    char uuid[36 + 1];

    GSSAPI_KRB5_INIT(&context);
    
    if (input_name_buffer->length < sizeof(uuid) - 1) {
	*minor_status = 0;
	return GSS_S_BAD_NAME;
    }
    
    memcpy(uuid, input_name_buffer->value, sizeof(uuid) - 1);
    uuid[sizeof(uuid) - 1] = '\0';
    
    /* validate that uuid is only uuid chars and the right length*/
    if (strspn(uuid, "0123456789abcdefABCDEF-") != 36) {
	*minor_status = 0;
	return GSS_S_BAD_NAME;
    }
    
    ret = krb5_make_principal(context, &princ, "UUID", uuid, NULL);
    if (ret) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }
    krb5_principal_set_type(context, princ, KRB5_NT_CACHE_UUID);
    
    *output_name = (gss_name_t)princ;
    *minor_status = 0;

    return GSS_S_COMPLETE;
}
コード例 #3
0
ファイル: import_name.c プロジェクト: DavidMulder/heimdal
static OM_uint32
import_hostbased_name(OM_uint32 *minor_status,
		      krb5_context context,
		      const gss_buffer_t input_name_buffer,
		      gss_name_t *output_name)
{
    krb5_principal princ = NULL;
    krb5_error_code kerr;
    char *tmp, *p, *host = NULL;

    tmp = malloc (input_name_buffer->length + 1);
    if (tmp == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }
    memcpy (tmp,
	    input_name_buffer->value,
	    input_name_buffer->length);
    tmp[input_name_buffer->length] = '\0';

    p = strchr (tmp, '@');
    if (p != NULL) {
	*p = '\0';
	host = p + 1;
    }

    kerr = krb5_make_principal(context, &princ, "", tmp, host, NULL);
    free (tmp);
    *minor_status = kerr;
    if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED)
	return GSS_S_BAD_NAME;
    else if (kerr)
	return GSS_S_FAILURE;

    krb5_principal_set_type(context, princ, KRB5_NT_SRV_HST);
    *output_name = (gss_name_t)princ;

    return 0;
}
コード例 #4
0
ファイル: kinit.c プロジェクト: brianmay/heimdal
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache  ccache;
    krb5_principal principal = NULL;
    int optidx = 0;
    krb5_deltat ticket_life = 0;
#ifdef HAVE_SIGACTION
    struct sigaction sa;
#endif

    setprogname(argv[0]);

    setlocale(LC_ALL, "");
    bindtextdomain("heimdal_kuser", HEIMDAL_LOCALEDIR);
    textdomain("heimdal_kuser");

    ret = krb5_init_context(&context);
    if (ret == KRB5_CONFIG_BADFORMAT)
	errx(1, "krb5_init_context failed to parse configuration file");
    else if (ret)
	errx(1, "krb5_init_context failed: %d", ret);

    if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage(0);

    if (version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    /*
     * Open the keytab now, we use the keytab to determine the principal's
     * realm when the requested principal has no realm.
     */
    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");
    }

    if (pk_enterprise_flag) {
	ret = krb5_pk_enterprise_cert(context, pk_user_id,
				      argv[0], &principal,
				      &ent_user_id);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_pk_enterprise_certs");

	pk_user_id = NULL;

    } else if (anonymous_flag) {

	ret = krb5_make_principal(context, &principal, argv[0],
				  KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME,
				  NULL);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_make_principal");
	krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN);

    } else if (use_keytab || keytab_str) {
	get_princ_kt(context, &principal, argv[0]);
    } else {
	get_princ(context, &principal, argv[0]);
    }

    if (fcache_version)
	krb5_set_fcache_version(context, fcache_version);

    if (renewable_flag == -1)
	/* this seems somewhat pointless, but whatever */
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"renewable", FALSE, &renewable_flag);
    if (do_afslog == -1)
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"afslog", TRUE, &do_afslog);

    if (cred_cache)
	ret = krb5_cc_resolve(context, cred_cache, &ccache);
    else {
	if (argc > 1) {
	    char s[1024];
	    ret = krb5_cc_new_unique(context, NULL, NULL, &ccache);
	    if (ret)
		krb5_err(context, 1, ret, "creating cred cache");
	    snprintf(s, sizeof(s), "%s:%s",
		     krb5_cc_get_type(context, ccache),
		     krb5_cc_get_name(context, ccache));
	    setenv("KRB5CCNAME", s, 1);
	} else {
	    ret = krb5_cc_cache_match(context, principal, &ccache);
	    if (ret) {
		const char *type;
		ret = krb5_cc_default(context, &ccache);
		if (ret)
		    krb5_err(context, 1, ret,
			     N_("resolving credentials cache", ""));

		/*
		 * Check if the type support switching, and we do,
		 * then do that instead over overwriting the current
		 * default credential
		 */
		type = krb5_cc_get_type(context, ccache);
		if (krb5_cc_support_switch(context, type)) {
		    krb5_cc_close(context, ccache);
		    ret = get_switched_ccache(context, type, principal,
					      &ccache);
		}
	    }
	}
    }
    if (ret)
	krb5_err(context, 1, ret, N_("resolving credentials cache", ""));

#ifndef NO_AFS
    if (argc > 1 && k_hasafs())
	k_setpag();
#endif

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

	ticket_life = tmp;
    }

    if (addrs_flag == 0 && extra_addresses.num_strings > 0)
	krb5_errx(context, 1,
		  N_("specifying both extra addresses and "
		     "no addresses makes no sense", ""));
    {
	int i;
	krb5_addresses addresses;
	memset(&addresses, 0, sizeof(addresses));
	for(i = 0; i < extra_addresses.num_strings; i++) {
	    ret = krb5_parse_address(context, extra_addresses.strings[i],
				     &addresses);
	    if (ret == 0) {
		krb5_add_extra_addresses(context, &addresses);
		krb5_free_addresses(context, &addresses);
	    }
	}
	free_getarg_strings(&extra_addresses);
    }

    if (renew_flag || validate_flag) {
	ret = renew_validate(context, renew_flag, validate_flag,
			     ccache, server_str, ticket_life);

#ifndef NO_AFS
	if (ret == 0 && server_str == NULL && do_afslog && k_hasafs())
	    krb5_afslog(context, ccache, NULL, NULL);
#endif

	exit(ret != 0);
    }

    ret = get_new_tickets(context, principal, ccache, ticket_life, 1);
    if (ret)
	exit(1);

#ifndef NO_AFS
    if (ret == 0 && server_str == NULL && do_afslog && k_hasafs())
	krb5_afslog(context, ccache, NULL, NULL);
#endif

    if (argc > 1) {
	struct renew_ctx ctx;
	time_t timeout;

	timeout = ticket_lifetime(context, ccache, principal,
				  server_str, NULL) / 2;

	ctx.context = context;
	ctx.ccache = ccache;
	ctx.principal = principal;
	ctx.ticket_life = ticket_life;
	ctx.timeout = timeout;

#ifdef HAVE_SIGACTION
	memset(&sa, 0, sizeof(sa));
	sigemptyset(&sa.sa_mask);
	sa.sa_handler = handle_siginfo;

	sigaction(SIGINFO, &sa, NULL);
#endif

	ret = simple_execvp_timed(argv[1], argv+1,
				  renew_func, &ctx, timeout);
#define EX_NOEXEC	126
#define EX_NOTFOUND	127
	if (ret == EX_NOEXEC)
	    krb5_warnx(context, N_("permission denied: %s", ""), argv[1]);
	else if (ret == EX_NOTFOUND)
	    krb5_warnx(context, N_("command not found: %s", ""), argv[1]);

	krb5_cc_destroy(context, ccache);
#ifndef NO_AFS
	if (k_hasafs())
	    k_unlog();
#endif
    } else {
	krb5_cc_close(context, ccache);
	ret = 0;
    }
    krb5_free_principal(context, principal);
    if (kt)
	krb5_kt_close(context, kt);
    krb5_free_context(context);
    return ret;
}
コード例 #5
0
static void
ntlm_service(void *ctx, const heim_idata *req,
	     const heim_icred cred,
	     heim_ipc_complete complete,
	     heim_sipc_call cctx)
{
    NTLMRequest2 ntq;
    unsigned char sessionkey[16];
    heim_idata rep = { 0, NULL };
    krb5_context context = ctx;
    hdb_entry_ex *user = NULL;
    Key *key = NULL;
    NTLMReply ntp;
    size_t size;
    int ret;
    char *domain;

    kdc_log(context, config, 1, "digest-request: uid=%d",
	    (int)heim_ipc_cred_get_uid(cred));
    
    if (heim_ipc_cred_get_uid(cred) != 0) {
	(*complete)(cctx, EPERM, NULL);
	return;
    }

    ntp.success = 0;
    ntp.flags = 0;
    ntp.sessionkey = NULL;

    ret = decode_NTLMRequest2(req->data, req->length, &ntq, NULL);
    if (ret)
	goto failed;

    /* XXX forward to NetrLogonSamLogonEx() if not a local domain */
    if (strcmp(ntq.loginDomainName, "BUILTIN") == 0) {
	domain = ntq.loginDomainName;
    } else if (strcmp(ntq.loginDomainName, "") == 0) {
	domain = "BUILTIN";
    } else {
	ret = EINVAL;
	goto failed;
    }

    kdc_log(context, config, 1, "digest-request: user=%s/%s",
	    ntq.loginUserName, domain);

    if (ntq.lmchallenge.length != 8)
	goto failed;

    if (ntq.ntChallengeResponce.length == 0)
	goto failed;

    {
	krb5_principal client;

	ret = krb5_make_principal(context, &client, domain,
				  ntq.loginUserName, NULL);
	if (ret)
	    goto failed;

	krb5_principal_set_type(context, client, KRB5_NT_NTLM);

	ret = _kdc_db_fetch(context, config, client,
			    HDB_F_GET_CLIENT, NULL, NULL, &user);
	krb5_free_principal(context, client);
	if (ret)
	    goto failed;

	ret = hdb_enctype2key(context, &user->entry,
			      ETYPE_ARCFOUR_HMAC_MD5, &key);
	if (ret) {
	    krb5_set_error_message(context, ret, "NTLM missing arcfour key");
	    goto failed;
	}
    }

    kdc_log(context, config, 2,
	    "digest-request: found user, processing ntlm request", ret);

    if (ntq.ntChallengeResponce.length != 24) {
	struct ntlm_buf infotarget, answer;
	
	answer.length = ntq.ntChallengeResponce.length;
	answer.data = ntq.ntChallengeResponce.data;
	
	ret = heim_ntlm_verify_ntlm2(key->key.keyvalue.data,
				     key->key.keyvalue.length,
				     ntq.loginUserName,
				     ntq.loginDomainName,
				     0,
				     ntq.lmchallenge.data,
				     &answer,
				     &infotarget,
				     sessionkey);
	if (ret) {
	    goto failed;
	}
	
	free(infotarget.data);
	/* XXX verify info target */
	
    } else {
	struct ntlm_buf answer;
	
	if (ntq.flags & NTLM_NEG_NTLM2_SESSION) {
	    unsigned char sessionhash[MD5_DIGEST_LENGTH];
	    EVP_MD_CTX *md5ctx;
	    
	    /* the first first 8 bytes is the challenge, what is the other 16 bytes ? */
	    if (ntq.lmChallengeResponce.length != 24)
		goto failed;

	    md5ctx = EVP_MD_CTX_create();
	    EVP_DigestInit_ex(md5ctx, EVP_md5(), NULL);
	    EVP_DigestUpdate(md5ctx, ntq.lmchallenge.data, 8);
	    EVP_DigestUpdate(md5ctx, ntq.lmChallengeResponce.data, 8);
	    EVP_DigestFinal_ex(md5ctx, sessionhash, NULL);
	    EVP_MD_CTX_destroy(md5ctx);
	    memcpy(ntq.lmchallenge.data, sessionhash, ntq.lmchallenge.length);
	}
	
	ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data,
					key->key.keyvalue.length,
					ntq.lmchallenge.data, &answer);
	if (ret)
	    goto failed;
	
	if (ntq.ntChallengeResponce.length != answer.length ||
	    memcmp(ntq.ntChallengeResponce.data, answer.data, answer.length) != 0) {
	    free(answer.data);
	    ret = EINVAL;
	    goto failed;
	}
	free(answer.data);
	
	{
	    EVP_MD_CTX *ctx;
	    
	    ctx = EVP_MD_CTX_create();
	    EVP_DigestInit_ex(ctx, EVP_md4(), NULL);
	    EVP_DigestUpdate(ctx, key->key.keyvalue.data, key->key.keyvalue.length);
	    EVP_DigestFinal_ex(ctx, sessionkey, NULL);
	    EVP_MD_CTX_destroy(ctx);
	}
    }

    ntp.success = 1;

    ASN1_MALLOC_ENCODE(NTLMReply, rep.data, rep.length, &ntp, &size, ret);
    if (ret)
	goto failed;
    if (rep.length != size)
	abort();
    
  failed:
    kdc_log(context, config, 1, "digest-request: %d", ret);

    (*complete)(cctx, ret, &rep);

    free(rep.data);

    free_NTLMRequest2(&ntq);
    if (user)
	_kdc_free_ent (context, user);
}
コード例 #6
0
ファイル: import_name.c プロジェクト: aosm/Heimdal
static OM_uint32
import_krb5_name(OM_uint32 *minor_status,
		 gss_const_OID mech,
		 const gss_buffer_t input_name_buffer,
		 gss_const_OID input_name_type,
		 gss_name_t *output_name)
{
    krb5_context context;
    krb5_principal princ;
    krb5_error_code ret;
    char *tmp;

    GSSAPI_KRB5_INIT (&context);

    tmp = malloc (input_name_buffer->length + 1);
    if (tmp == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }
    memcpy (tmp,
	    input_name_buffer->value,
	    input_name_buffer->length);
    tmp[input_name_buffer->length] = '\0';

    if (tmp[0] == '@') {
	princ = calloc(1, sizeof(*princ));
	if (princ == NULL) {
	    free(tmp);
	    *minor_status = ENOMEM;
	    return GSS_S_FAILURE;
	}

	princ->realm = strdup(&tmp[1]);
	if (princ->realm == NULL) {
	    free(tmp);
	    free(princ);
	    return GSS_S_FAILURE;
	}
    } else {
	ret = krb5_parse_name (context, tmp, &princ);
	if (ret) {
	    free(tmp);
	    *minor_status = ret;

	    if (ret == KRB5_PARSE_ILLCHAR || ret == KRB5_PARSE_MALFORMED)
		return GSS_S_BAD_NAME;

	    return GSS_S_FAILURE;
	}
    }

    if (mech && gss_oid_equal(mech, GSS_PKU2U_MECHANISM) && strchr(tmp, '@') == NULL)
	krb5_principal_set_realm(context, princ, KRB5_PKU2U_REALM_NAME);

    free(tmp);

    if (princ->name.name_string.len == 2 &&
	gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME_REFERRAL))
	krb5_principal_set_type(context, princ, KRB5_NT_GSS_HOSTBASED_SERVICE);

    *output_name = (gss_name_t)princ;
    return GSS_S_COMPLETE;
}
コード例 #7
0
ファイル: import_name.c プロジェクト: aosm/Heimdal
static OM_uint32
import_hostbased_name (OM_uint32 *minor_status,
		       gss_const_OID mech,
		       const gss_buffer_t input_name_buffer,
		       gss_const_OID input_name_type,
		       gss_name_t *output_name)
{
    krb5_context context;
    krb5_principal princ = NULL;
    krb5_error_code kerr;
    char *tmp, *p, *host = NULL, *realm = NULL;

    if (gss_oid_equal(mech, GSS_PKU2U_MECHANISM))
	realm = KRB5_PKU2U_REALM_NAME;
    else
	realm = KRB5_GSS_REFERALS_REALM_NAME; /* should never hit the network */

    GSSAPI_KRB5_INIT (&context);

    tmp = malloc (input_name_buffer->length + 1);
    if (tmp == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }
    memcpy (tmp,
	    input_name_buffer->value,
	    input_name_buffer->length);
    tmp[input_name_buffer->length] = '\0';

    p = strchr (tmp, '@');
    if (p != NULL && p[1] != '\0') {
	size_t len;

	*p = '\0';
	host = p + 1;

	/*
	 * Squash any trailing . on the hostname since that is jolly
	 * good to have when looking up a DNS name (qualified), but
	 * its no good to have in the kerberos principal since those
	 * are supposed to be in qualified format already.
	 */

	len = strlen(host);
	if (len > 0 && host[len - 1] == '.')
	    host[len - 1] = '\0';
    } else {
	host = KRB5_GSS_HOSTBASED_SERVICE_NAME;
    }

    kerr = krb5_make_principal(context, &princ, realm, tmp, host, NULL);
    free (tmp);
    *minor_status = kerr;
    if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED)
	return GSS_S_BAD_NAME;
    else if (kerr)
	return GSS_S_FAILURE;

    krb5_principal_set_type(context, princ, KRB5_NT_GSS_HOSTBASED_SERVICE);
    *output_name = (gss_name_t)princ;

    return 0;
}