Пример #1
0
static void gp_set_cred_options(gssx_cred *cred, gss_cred_id_t gss_cred)
{
    struct gssx_cred_element *ce;
    struct gssx_option *op;
    uint32_t num_ktypes = 0;
    krb5_enctype *ktypes;
    uint32_t maj, min;
    int i, j;

    for (i = 0; i < cred->elements.elements_len; i++) {
        ce = &cred->elements.elements_val[i];
        for (j = 0; j < ce->options.options_len; j++) {
            op = &ce->options.options_val[j];
            if ((op->option.octet_string_len ==
                    sizeof(KRB5_SET_ALLOWED_ENCTYPE)) &&
                (strncmp(KRB5_SET_ALLOWED_ENCTYPE,
                         op->option.octet_string_val,
                         op->option.octet_string_len) == 0)) {
                num_ktypes = op->value.octet_string_len / sizeof(krb5_enctype);
                ktypes = (krb5_enctype *)op->value.octet_string_val;
                break;
            }
        }
    }

    if (num_ktypes) {
        maj = gss_krb5_set_allowable_enctypes(&min, gss_cred,
                                              num_ktypes, ktypes);
        if (maj != GSS_S_COMPLETE) {
            GPDEBUG("Failed to set allowable enctypes\n");
        }
    }
}
Пример #2
0
int
main(int argc, char *argv[])
{
    krb5_error_code ret;
    krb5_context kctx = NULL;
    krb5_enctype *ienc = NULL, *aenc = NULL, zero = 0;
    OM_uint32 minor, major, flags;
    gss_name_t tname;
    gss_cred_id_t icred = GSS_C_NO_CREDENTIAL, acred = GSS_C_NO_CREDENTIAL;
    gss_ctx_id_t ictx, actx;
    gss_krb5_lucid_context_v1_t *ilucid, *alucid;
    gss_krb5_rfc1964_keydata_t *i1964, *a1964;
    gss_krb5_cfx_keydata_t *icfx, *acfx;
    size_t count;
    void *lptr;
    int c;

    ret = krb5_init_context(&kctx);
    check_k5err(kctx, "krb5_init_context", ret);

    /* Parse arguments. */
    while ((c = getopt(argc, argv, "i:a:")) != -1) {
        switch (c) {
        case 'i':
            ret = krb5int_parse_enctype_list(kctx, "", optarg, &zero, &ienc);
            check_k5err(kctx, "krb5_parse_enctype_list(initiator)", ret);
            break;
        case 'a':
            ret = krb5int_parse_enctype_list(kctx, "", optarg, &zero, &aenc);
            check_k5err(kctx, "krb5_parse_enctype_list(acceptor)", ret);
            break;
        default:
            usage();
        }
    }
    argc -= optind;
    argv += optind;
    if (argc != 1)
        usage();
    tname = import_name(*argv);

    if (ienc != NULL) {
        major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
                                 &mechset_krb5, GSS_C_INITIATE, &icred, NULL,
                                 NULL);
        check_gsserr("gss_acquire_cred(initiator)", major, minor);

        for (count = 0; ienc[count]; count++);
        major = gss_krb5_set_allowable_enctypes(&minor, icred, count, ienc);
        check_gsserr("gss_krb5_set_allowable_enctypes(init)", major, minor);
    }
    if (aenc != NULL) {
        major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
                                 &mechset_krb5, GSS_C_ACCEPT, &acred, NULL,
                                 NULL);
        check_gsserr("gss_acquire_cred(acceptor)", major, minor);

        for (count = 0; aenc[count]; count++);
        major = gss_krb5_set_allowable_enctypes(&minor, acred, count, aenc);
        check_gsserr("gss_krb5_set_allowable_enctypes(acc)", major, minor);
    }

    flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG;
    establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx,
                       NULL, NULL, NULL);

    /* Export to lucid contexts. */
    major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr);
    check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor);
    ilucid = lptr;
    major = gss_krb5_export_lucid_sec_context(&minor, &actx, 1, &lptr);
    check_gsserr("gss_export_lucid_sec_context(acceptor)", major, minor);
    alucid = lptr;

    /* Grab the session keys and make sure they match. */
    if (ilucid->protocol != alucid->protocol)
        errout("Initiator/acceptor protocol mismatch");
    if (ilucid->protocol) {
        icfx = &ilucid->cfx_kd;
        acfx = &alucid->cfx_kd;
        if (icfx->have_acceptor_subkey != acfx->have_acceptor_subkey)
            errout("Initiator/acceptor have_acceptor_subkey mismatch");
        check_key_match(&icfx->ctx_key, &acfx->ctx_key);
        if (icfx->have_acceptor_subkey)
            check_key_match(&icfx->acceptor_subkey, &acfx->acceptor_subkey);
        fputs("cfx ", stdout);
        display_enctype(icfx->ctx_key.type);
        if (icfx->have_acceptor_subkey) {
            fputs(" ", stdout);
            display_enctype(icfx->acceptor_subkey.type);
        }
        fputs("\n", stdout);
    } else {
        i1964 = &ilucid->rfc1964_kd;
        a1964 = &alucid->rfc1964_kd;
        if (i1964->sign_alg != a1964->sign_alg ||
            i1964->seal_alg != a1964->seal_alg)
            errout("Initiator/acceptor sign or seal alg mismatch");
        check_key_match(&i1964->ctx_key, &a1964->ctx_key);
        fputs("rfc1964 ", stdout);
        display_enctype(i1964->ctx_key.type);
        fputs("\n", stdout);
    }

    krb5_free_context(kctx);
    free(ienc);
    free(aenc);
    (void)gss_release_name(&minor, &tname);
    (void)gss_release_cred(&minor, &icred);
    (void)gss_release_cred(&minor, &acred);
    (void)gss_delete_sec_context(&minor, &ictx, NULL);
    (void)gss_delete_sec_context(&minor, &actx, NULL);
    (void)gss_krb5_free_lucid_sec_context(&minor, ilucid);
    (void)gss_krb5_free_lucid_sec_context(&minor, alucid);
    return 0;
}
Пример #3
0
_PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, 
						  struct tevent_context *event_ctx,
						  struct loadparm_context *lp_ctx,
						  struct gssapi_creds_container **_gcc,
						  const char **error_string)
{
	int ret = 0;
	OM_uint32 maj_stat, min_stat;
	struct gssapi_creds_container *gcc;
	struct ccache_container *ccache;
#ifdef SAMBA4_USES_HEIMDAL
	gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
#endif
	krb5_enctype *etypes = NULL;

	if (cred->client_gss_creds_obtained >= cred->client_gss_creds_threshold && 
	    cred->client_gss_creds_obtained > CRED_UNINITIALISED) {
		bool expired = false;
		OM_uint32 lifetime = 0;
		gss_cred_usage_t usage = 0;
		maj_stat = gss_inquire_cred(&min_stat, cred->client_gss_creds->creds, 
					    NULL, &lifetime, &usage, NULL);
		if (maj_stat == GSS_S_CREDENTIALS_EXPIRED) {
			DEBUG(3, ("Credentials for %s expired, must refresh credentials cache\n", cli_credentials_get_principal(cred, cred)));
			expired = true;
		} else if (maj_stat == GSS_S_COMPLETE && lifetime < 300) {
			DEBUG(3, ("Credentials for %s will expire shortly (%u sec), must refresh credentials cache\n", cli_credentials_get_principal(cred, cred), lifetime));
			expired = true;
		} else if (maj_stat != GSS_S_COMPLETE) {
			*error_string = talloc_asprintf(cred, "inquiry of credential lifefime via GSSAPI gss_inquire_cred failed: %s\n",
							gssapi_error_string(cred, maj_stat, min_stat, NULL));
			return EINVAL;
		}
		if (expired) {
			cli_credentials_unconditionally_invalidate_client_gss_creds(cred);
		} else {
			DEBUG(5, ("GSSAPI credentials for %s will expire in %u secs\n", 
				  cli_credentials_get_principal(cred, cred), (unsigned int)lifetime));
		
			*_gcc = cred->client_gss_creds;
			return 0;
		}
	}

	ret = cli_credentials_get_ccache(cred, event_ctx, lp_ctx,
					 &ccache, error_string);
	if (ret) {
		if (cli_credentials_get_kerberos_state(cred) == CRED_MUST_USE_KERBEROS) {
			DEBUG(1, ("Failed to get kerberos credentials (kerberos required): %s\n", *error_string));
		} else {
			DEBUG(4, ("Failed to get kerberos credentials: %s\n", *error_string));
		}
		return ret;
	}

	gcc = talloc(cred, struct gssapi_creds_container);
	if (!gcc) {
		(*error_string) = error_message(ENOMEM);
		return ENOMEM;
	}

	maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL, 
					&gcc->creds);
	if ((maj_stat == GSS_S_FAILURE) && (min_stat == (OM_uint32)KRB5_CC_END || min_stat == (OM_uint32) KRB5_CC_NOTFOUND)) {
		/* This CCACHE is no good.  Ensure we don't use it again */
		cli_credentials_unconditionally_invalidate_ccache(cred);

		/* Now try again to get a ccache */
		ret = cli_credentials_get_ccache(cred, event_ctx, lp_ctx,
						 &ccache, error_string);
		if (ret) {
			DEBUG(1, ("Failed to re-get CCACHE for GSSAPI client: %s\n", error_message(ret)));
			return ret;
		}

		maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL,
						&gcc->creds);

	}

	if (maj_stat) {
		talloc_free(gcc);
		if (min_stat) {
			ret = min_stat;
		} else {
			ret = EINVAL;
		}
		(*error_string) = talloc_asprintf(cred, "gss_krb5_import_cred failed: %s", error_message(ret));
		return ret;
	}


	/*
	 * transfer the enctypes from the smb_krb5_context to the gssapi layer
	 *
	 * We use 'our' smb_krb5_context to do the AS-REQ and it is possible
	 * to configure the enctypes via the krb5.conf.
	 *
	 * And the gss_init_sec_context() creates it's own krb5_context and
	 * the TGS-REQ had all enctypes in it and only the ones configured
	 * and used for the AS-REQ, so it wasn't possible to disable the usage
	 * of AES keys.
	 */
	min_stat = get_kerberos_allowed_etypes(ccache->smb_krb5_context->krb5_context,
					       &etypes);
	if (min_stat == 0) {
		OM_uint32 num_ktypes;

		for (num_ktypes = 0; etypes[num_ktypes]; num_ktypes++);

		maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, gcc->creds,
							   num_ktypes,
							   (int32_t *) etypes);
		SAFE_FREE(etypes);
		if (maj_stat) {
			talloc_free(gcc);
			if (min_stat) {
				ret = min_stat;
			} else {
				ret = EINVAL;
			}
			(*error_string) = talloc_asprintf(cred, "gss_krb5_set_allowable_enctypes failed: %s", error_message(ret));
			return ret;
		}
	}

#ifdef SAMBA4_USES_HEIMDAL /* MIT lacks GSS_KRB5_CRED_NO_CI_FLAGS_X */

	/* don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG */
	maj_stat = gss_set_cred_option(&min_stat, &gcc->creds,
				       GSS_KRB5_CRED_NO_CI_FLAGS_X,
				       &empty_buffer);
	if (maj_stat) {
		talloc_free(gcc);
		if (min_stat) {
			ret = min_stat;
		} else {
			ret = EINVAL;
		}
		(*error_string) = talloc_asprintf(cred, "gss_set_cred_option failed: %s", error_message(ret));
		return ret;
	}
#endif
	cred->client_gss_creds_obtained = cred->ccache_obtained;
	talloc_set_destructor(gcc, free_gssapi_creds);
	cred->client_gss_creds = gcc;
	*_gcc = gcc;
	return 0;
}
Пример #4
0
int
main(int argc, char **argv)
{
    gss_OID_set oidset = GSS_C_NULL_OID_SET;
    gss_OID mechoid = GSS_C_NO_OID;
    OM_uint32 maj_stat, min_stat;
    gss_cred_id_t cred;
    gss_name_t target = GSS_C_NO_NAME;
    int i, optidx = 0;
    gss_cred_usage_t cred_usage = GSS_C_BOTH;
    gss_OID type = GSS_C_NT_HOSTBASED_SERVICE;
    gss_key_value_set_desc store, *storep = GSS_C_NO_CRED_STORE;
    gss_key_value_element_desc elements[2];

    store.count = 0;
    store.elements = elements;

    setprogname(argv[0]);
    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;

    if (argc != 0)
	usage(1);

    if (acquire_type) {
	if (strcasecmp(acquire_type, "both") == 0)
	    cred_usage = GSS_C_BOTH;
	else if (strcasecmp(acquire_type, "accept") == 0)
	    cred_usage = GSS_C_ACCEPT;
	else if (strcasecmp(acquire_type, "initiate") == 0)
	    cred_usage = GSS_C_INITIATE;
	else
	    errx(1, "unknown type %s", acquire_type);
    }

    if (name_type) {
	if (strcasecmp("hostbased-service", name_type) == 0)
	    type = GSS_C_NT_HOSTBASED_SERVICE;
	else if (strcasecmp("user-name", name_type) == 0)
	    type = GSS_C_NT_USER_NAME;
	else
	    errx(1, "unknown name type %s", name_type);
    }

    if (ccache) {
	store.elements[store.count].key = "ccache";
	store.elements[store.count].value = ccache;
	store.count++;
    }
    if (client_keytab) {
	store.elements[store.count].key = "client_keytab";
	store.elements[store.count].value = client_keytab;
	store.count++;
    }

    if (store.count)
	storep = &store;

    if (kerberos_flag) {
	mechoid = GSS_KRB5_MECHANISM;

	maj_stat = gss_create_empty_oid_set(&min_stat, &oidset);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_create_empty_oid_set: %s",
		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));

	maj_stat = gss_add_oid_set_member(&min_stat, GSS_KRB5_MECHANISM, &oidset);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_add_oid_set_member: %s",
		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    }

    if (target_name) {
	gss_buffer_desc name;

	name.value = target_name;
	name.length = strlen(target_name);
	maj_stat = gss_import_name(&min_stat, &name,
				   GSS_C_NT_HOSTBASED_SERVICE, &target);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_import_name: %s",
		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    }

    for (i = 0; i < num_loops; i++) {

	cred = acquire_cred_service(acquire_name, type, oidset, cred_usage, storep);

	if (enctype) {
	    int32_t enctypelist = enctype;

	    maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, cred,
						       1, &enctypelist);
	    if (maj_stat)
		errx(1, "gss_krb5_set_allowable_enctypes: %s",
		     gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
	}

	if (target) {
	    gss_ctx_id_t context = GSS_C_NO_CONTEXT;
	    gss_buffer_desc out;

	    out.length = 0;
	    out.value = NULL;

	    maj_stat = gss_init_sec_context(&min_stat,
					    cred, &context,
					    target, mechoid,
					    GSS_C_MUTUAL_FLAG, 0, NULL,
					    GSS_C_NO_BUFFER, NULL,
					    &out, NULL, NULL);
	    if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
		errx(1, "init_sec_context failed: %s",
		     gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));

	    gss_release_buffer(&min_stat, &out);
	    gss_delete_sec_context(&min_stat, &context, NULL);
	}
	gss_release_cred(&min_stat, &cred);
    }


    return 0;
}
Пример #5
0
int
main(int argc, char **argv)
{
	struct module_stat stat;
	int mod;
	int syscall_num;

	stat.version = sizeof(stat);
	mod = modfind("gsstest_syscall");
	if (mod < 0) {
		fprintf(stderr, "%s: kernel support not present\n", argv[0]);
		exit(1);
	}
	modstat(mod, &stat);
	syscall_num = stat.data.intval;

	switch (atoi(argv[1])) {
	case 1:
		syscall(syscall_num, 1, NULL, NULL);
		break;

	case 2: {
		struct gsstest_2_args args;
		struct gsstest_2_res res;
		char hostname[512];
		char token_buffer[8192];
		OM_uint32 maj_stat, min_stat;
		gss_ctx_id_t client_context = GSS_C_NO_CONTEXT;
		gss_cred_id_t client_cred;
		gss_OID mech_type = GSS_C_NO_OID;
		gss_buffer_desc name_buf, message_buf;
		gss_name_t name;
		int32_t enctypes[] = {
			ETYPE_DES_CBC_CRC,
			ETYPE_ARCFOUR_HMAC_MD5,
			ETYPE_ARCFOUR_HMAC_MD5_56,
			ETYPE_AES256_CTS_HMAC_SHA1_96,
			ETYPE_AES128_CTS_HMAC_SHA1_96,
			ETYPE_DES3_CBC_SHA1,
		};
		int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
		int established;
		int i;

		for (i = 0; i < num_enctypes; i++) {
			printf("testing etype %d\n", enctypes[i]);
			args.output_token.length = sizeof(token_buffer);
			args.output_token.value = token_buffer;

			gethostname(hostname, sizeof(hostname));
			snprintf(token_buffer, sizeof(token_buffer),
			    "nfs@%s", hostname);
			name_buf.length = strlen(token_buffer);
			name_buf.value = token_buffer;
			maj_stat = gss_import_name(&min_stat, &name_buf,
			    GSS_C_NT_HOSTBASED_SERVICE, &name);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_import_name failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}

			maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME,
			    0, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client_cred,
			    NULL, NULL);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_acquire_cred (client) failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}

			maj_stat = gss_krb5_set_allowable_enctypes(&min_stat,
			    client_cred, 1, &enctypes[i]);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_krb5_set_allowable_enctypes failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}

			res.output_token.length = 0;
			res.output_token.value = 0;
			established = 0;
			while (!established) {
				maj_stat = gss_init_sec_context(&min_stat,
				    client_cred,
				    &client_context,
				    name,
				    GSS_C_NO_OID,
				    (GSS_C_MUTUAL_FLAG
					|GSS_C_CONF_FLAG
					|GSS_C_INTEG_FLAG
					|GSS_C_SEQUENCE_FLAG
					|GSS_C_REPLAY_FLAG),
				    0,
				    GSS_C_NO_CHANNEL_BINDINGS,
				    &res.output_token,
				    &mech_type,
				    &args.input_token,
				    NULL,
				    NULL);
				if (GSS_ERROR(maj_stat)) {
					printf("gss_init_sec_context failed\n");
					report_error(mech_type, maj_stat, min_stat);
					goto out;
				}
				if (args.input_token.length) {
					args.step = 1;
					syscall(syscall_num, 2, &args, &res);
					gss_release_buffer(&min_stat,
					    &args.input_token);
					if (res.maj_stat != GSS_S_COMPLETE
					    && res.maj_stat != GSS_S_CONTINUE_NEEDED) {
						printf("gss_accept_sec_context (kernel) failed\n");
						report_error(mech_type, res.maj_stat,
						    res.min_stat);
						goto out;
					}
				}
				if (maj_stat == GSS_S_COMPLETE)
					established = 1;
			}

			message_buf.value = "Hello world";
			message_buf.length = strlen((char *) message_buf.value);

			maj_stat = gss_get_mic(&min_stat, client_context,
			    GSS_C_QOP_DEFAULT, &message_buf, &args.input_token);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_get_mic failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}
		
			args.step = 2;
			syscall(syscall_num, 2, &args, &res);
			gss_release_buffer(&min_stat, &args.input_token);
			if (GSS_ERROR(res.maj_stat)) {
				printf("kernel gss_verify_mic failed\n");
				report_error(mech_type, res.maj_stat, res.min_stat);
				goto out;
			}

			maj_stat = gss_verify_mic(&min_stat, client_context,
			    &message_buf, &res.output_token, NULL);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_verify_mic failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}

			maj_stat = gss_wrap(&min_stat, client_context,
			    TRUE, GSS_C_QOP_DEFAULT, &message_buf, NULL,
			    &args.input_token);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_wrap failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}

			args.step = 3;
			syscall(syscall_num, 2, &args, &res);
			gss_release_buffer(&min_stat, &args.input_token);
			if (GSS_ERROR(res.maj_stat)) {
				printf("kernel gss_unwrap failed\n");
				report_error(mech_type, res.maj_stat, res.min_stat);
				goto out;
			}

			maj_stat = gss_unwrap(&min_stat, client_context,
			    &res.output_token, &message_buf, NULL, NULL);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_unwrap failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}
			gss_release_buffer(&min_stat, &message_buf);

			maj_stat = gss_wrap(&min_stat, client_context,
			    FALSE, GSS_C_QOP_DEFAULT, &message_buf, NULL,
			    &args.input_token);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_wrap failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}

			args.step = 4;
			syscall(syscall_num, 2, &args, &res);
			gss_release_buffer(&min_stat, &args.input_token);
			if (GSS_ERROR(res.maj_stat)) {
				printf("kernel gss_unwrap failed\n");
				report_error(mech_type, res.maj_stat, res.min_stat);
				goto out;
			}

			maj_stat = gss_unwrap(&min_stat, client_context,
			    &res.output_token, &message_buf, NULL, NULL);
			if (GSS_ERROR(maj_stat)) {
				printf("gss_unwrap failed\n");
				report_error(mech_type, maj_stat, min_stat);
				goto out;
			}
			gss_release_buffer(&min_stat, &message_buf);

			args.step = 5;
			syscall(syscall_num, 2, &args, &res);

			gss_release_name(&min_stat, &name);
			gss_release_cred(&min_stat, &client_cred);
			gss_delete_sec_context(&min_stat, &client_context,
			    GSS_C_NO_BUFFER);
		}

		break;
	}
	case 3:
		syscall(syscall_num, 3, NULL, NULL);
		break;
	case 4:
		syscall(syscall_num, 4, NULL, NULL);
		break;
	}
	return (0);

out:
	return (1);
}
Пример #6
0
int
main(int argc, char **argv)
{
    int optind = 0;
    OM_uint32 min_stat, maj_stat;
    gss_ctx_id_t cctx, sctx;
    void *ctx;
    gss_OID nameoid, mechoid, actual_mech, actual_mech2;
    gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL;
    gss_name_t cname = GSS_C_NO_NAME;
    gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER;

    setprogname(argv[0]);

    init_o2n();

    if (krb5_init_context(&context))
	errx(1, "krb5_init_context");

    cctx = sctx = GSS_C_NO_CONTEXT;

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

    if (help_flag)
	usage (0);

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

    argc -= optind;
    argv += optind;

    if (argc != 1)
	usage(1);

    if (dns_canon_flag != -1)
	gsskrb5_set_dns_canonicalize(dns_canon_flag);

    if (type_string == NULL)
	nameoid = GSS_C_NT_HOSTBASED_SERVICE;
    else if (strcmp(type_string, "hostbased-service") == 0)
	nameoid = GSS_C_NT_HOSTBASED_SERVICE;
    else if (strcmp(type_string, "krb5-principal-name") == 0)
	nameoid = GSS_KRB5_NT_PRINCIPAL_NAME;
    else
	errx(1, "%s not suppported", type_string);

    if (mech_string == NULL)
	mechoid = GSS_KRB5_MECHANISM;
    else
	mechoid = string_to_oid(mech_string);

    if (gsskrb5_acceptor_identity) {
	maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity);
	if (maj_stat)
	    errx(1, "gsskrb5_acceptor_identity: %s",
		 gssapi_err(maj_stat, 0, GSS_C_NO_OID));
    }

    if (client_password) {
	credential_data.value = client_password;
	credential_data.length = strlen(client_password);
    }

    if (client_name) {
	gss_buffer_desc cn;

	cn.value = client_name;
	cn.length = strlen(client_name);

	maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname);
	if (maj_stat)
	    errx(1, "gss_import_name: %s",
		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    }

    if (client_password) {
	maj_stat = gss_acquire_cred_with_password(&min_stat,
						  cname,
						  &credential_data,
						  GSS_C_INDEFINITE,
						  GSS_C_NO_OID_SET,
						  GSS_C_INITIATE,
						  &client_cred,
						  NULL,
						  NULL);
	if (GSS_ERROR(maj_stat))
	    errx(1, "gss_acquire_cred_with_password: %s",
		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    } else {
	maj_stat = gss_acquire_cred(&min_stat,
				    cname,
				    GSS_C_INDEFINITE,
				    GSS_C_NO_OID_SET,
				    GSS_C_INITIATE,
				    &client_cred,
				    NULL,
				    NULL);
	if (GSS_ERROR(maj_stat))
	    errx(1, "gss_acquire_cred: %s",
		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    }

    if (limit_enctype_string) {
	krb5_error_code ret;

	ret = krb5_string_to_enctype(context,
				     limit_enctype_string,
				     &limit_enctype);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_string_to_enctype");
    }


    if (limit_enctype) {
	if (client_cred == NULL)
	    errx(1, "client_cred missing");

	maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred,
						   1, &limit_enctype);
	if (maj_stat)
	    errx(1, "gss_krb5_set_allowable_enctypes: %s",
		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    }

    loop(mechoid, nameoid, argv[0], client_cred,
	 &sctx, &cctx, &actual_mech, &deleg_cred);

    if (verbose_flag)
	printf("resulting mech: %s\n", oid_to_string(actual_mech));

    if (ret_mech_string) {
	gss_OID retoid;

	retoid = string_to_oid(ret_mech_string);

	if (gss_oid_equal(retoid, actual_mech) == 0)
	    errx(1, "actual_mech mech is not the expected type %s",
		 ret_mech_string);
    }

    /* XXX should be actual_mech */
    if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) {
	time_t time;
	gss_buffer_desc authz_data;
	gss_buffer_desc in, out1, out2;
	krb5_keyblock *keyblock, *keyblock2;
	krb5_timestamp now;
	krb5_error_code ret;

	ret = krb5_timeofday(context, &now);
	if (ret)
	    errx(1, "krb5_timeofday failed");

	/* client */
	maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
						     &cctx,
						     1, /* version */
						     &ctx);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
		 gssapi_err(maj_stat, min_stat, actual_mech));


	maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
		     gssapi_err(maj_stat, min_stat, actual_mech));

	/* server */
	maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
						     &sctx,
						     1, /* version */
						     &ctx);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
		     gssapi_err(maj_stat, min_stat, actual_mech));
	maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
		     gssapi_err(maj_stat, min_stat, actual_mech));

 	maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,
							     sctx,
							     &time);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s",
		     gssapi_err(maj_stat, min_stat, actual_mech));

	if (time > now)
	    errx(1, "gsskrb5_extract_authtime_from_sec_context failed: "
		 "time authtime is before now: %ld %ld",
		 (long)time, (long)now);

 	maj_stat = gsskrb5_extract_service_keyblock(&min_stat,
						    sctx,
						    &keyblock);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gsskrb5_export_service_keyblock failed: %s",
		     gssapi_err(maj_stat, min_stat, actual_mech));

	krb5_free_keyblock(context, keyblock);

 	maj_stat = gsskrb5_get_subkey(&min_stat,
				      sctx,
				      &keyblock);
	if (maj_stat != GSS_S_COMPLETE
	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
	    errx(1, "gsskrb5_get_subkey server failed: %s",
		     gssapi_err(maj_stat, min_stat, actual_mech));

	if (maj_stat != GSS_S_COMPLETE)
	    keyblock = NULL;
	else if (limit_enctype && keyblock->keytype != limit_enctype)
	    errx(1, "gsskrb5_get_subkey wrong enctype");

 	maj_stat = gsskrb5_get_subkey(&min_stat,
				      cctx,
				      &keyblock2);
	if (maj_stat != GSS_S_COMPLETE
	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
	    errx(1, "gsskrb5_get_subkey client failed: %s",
		     gssapi_err(maj_stat, min_stat, actual_mech));

	if (maj_stat != GSS_S_COMPLETE)
	    keyblock2 = NULL;
	else if (limit_enctype && keyblock->keytype != limit_enctype)
	    errx(1, "gsskrb5_get_subkey wrong enctype");

	if (keyblock || keyblock2) {
	    if (keyblock == NULL)
		errx(1, "server missing token keyblock");
	    if (keyblock2 == NULL)
		errx(1, "client missing token keyblock");

	    if (keyblock->keytype != keyblock2->keytype)
		errx(1, "enctype mismatch");
	    if (keyblock->keyvalue.length != keyblock2->keyvalue.length)
		errx(1, "key length mismatch");
	    if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data,
		       keyblock2->keyvalue.length) != 0)
		errx(1, "key data mismatch");
	}

	if (session_enctype_string) {
	    krb5_enctype enctype;

	    ret = krb5_string_to_enctype(context,
					 session_enctype_string,
					 &enctype);

	    if (ret)
		krb5_err(context, 1, ret, "krb5_string_to_enctype");

	    if (enctype != keyblock->keytype)
		errx(1, "keytype is not the expected %d != %d",
		     (int)enctype, (int)keyblock2->keytype);
	}

	if (keyblock)
	    krb5_free_keyblock(context, keyblock);
	if (keyblock2)
	    krb5_free_keyblock(context, keyblock2);

 	maj_stat = gsskrb5_get_initiator_subkey(&min_stat,
						sctx,
						&keyblock);
	if (maj_stat != GSS_S_COMPLETE
	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
	    errx(1, "gsskrb5_get_initiator_subkey failed: %s",
		     gssapi_err(maj_stat, min_stat, actual_mech));

	if (maj_stat == GSS_S_COMPLETE) {

	    if (limit_enctype && keyblock->keytype != limit_enctype)
		errx(1, "gsskrb5_get_initiator_subkey wrong enctype");
	    krb5_free_keyblock(context, keyblock);
	}

 	maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
							       sctx,
							       128,
							       &authz_data);
	if (maj_stat == GSS_S_COMPLETE)
	    gss_release_buffer(&min_stat, &authz_data);


	memset(&out1, 0, sizeof(out1));
	memset(&out2, 0, sizeof(out2));

	in.value = "foo";
	in.length = 3;

	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
			  100, &out1);
	gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in,
			  100, &out2);

	if (out1.length != out2.length)
	    errx(1, "prf len mismatch");
	if (memcmp(out1.value, out2.value, out1.length) != 0)
	    errx(1, "prf data mismatch");

	gss_release_buffer(&min_stat, &out1);

	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
			  100, &out1);

	if (out1.length != out2.length)
	    errx(1, "prf len mismatch");
	if (memcmp(out1.value, out2.value, out1.length) != 0)
	    errx(1, "prf data mismatch");

	gss_release_buffer(&min_stat, &out1);
	gss_release_buffer(&min_stat, &out2);

	in.value = "bar";
	in.length = 3;

	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in,
			  100, &out1);
	gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in,
			  100, &out2);

	if (out1.length != out2.length)
	    errx(1, "prf len mismatch");
	if (memcmp(out1.value, out2.value, out1.length) != 0)
	    errx(1, "prf data mismatch");

	gss_release_buffer(&min_stat, &out1);
	gss_release_buffer(&min_stat, &out2);

	wrapunwrap_flag = 1;
	getverifymic_flag = 1;
    }

    if (wrapunwrap_flag) {
	wrapunwrap(cctx, sctx, 0, actual_mech);
	wrapunwrap(cctx, sctx, 1, actual_mech);
	wrapunwrap(sctx, cctx, 0, actual_mech);
	wrapunwrap(sctx, cctx, 1, actual_mech);
    }

    if (iov_flag) {
	wrapunwrap_iov(cctx, sctx, 0, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);

	wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);

	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech);

/* works */
	wrapunwrap_iov(cctx, sctx, 0, actual_mech);
	wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);

	wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);

	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);

	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);

	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);

	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
    }

    if (getverifymic_flag) {
	getverifymic(cctx, sctx, actual_mech);
	getverifymic(cctx, sctx, actual_mech);
	getverifymic(sctx, cctx, actual_mech);
	getverifymic(sctx, cctx, actual_mech);
    }


    gss_delete_sec_context(&min_stat, &cctx, NULL);
    gss_delete_sec_context(&min_stat, &sctx, NULL);

    if (deleg_cred != GSS_C_NO_CREDENTIAL) {
	gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL;
	gss_buffer_desc cb;

	if (verbose_flag)
	    printf("checking actual mech (%s) on delegated cred\n",
		   oid_to_string(actual_mech));
	loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2);

	gss_delete_sec_context(&min_stat, &cctx, NULL);
	gss_delete_sec_context(&min_stat, &sctx, NULL);

	gss_release_cred(&min_stat, &cred2);

	/* try again using SPNEGO */
	if (verbose_flag)
	    printf("checking spnego on delegated cred\n");
	loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx,
	     &actual_mech2, &cred2);

	gss_delete_sec_context(&min_stat, &cctx, NULL);
	gss_delete_sec_context(&min_stat, &sctx, NULL);

	gss_release_cred(&min_stat, &cred2);

	/* check export/import */
	if (ei_flag) {

	    maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb);
	    if (maj_stat != GSS_S_COMPLETE)
		errx(1, "export failed: %s",
		     gssapi_err(maj_stat, min_stat, NULL));

	    maj_stat = gss_import_cred(&min_stat, &cb, &cred2);
	    if (maj_stat != GSS_S_COMPLETE)
		errx(1, "import failed: %s",
		     gssapi_err(maj_stat, min_stat, NULL));

	    gss_release_buffer(&min_stat, &cb);
	    gss_release_cred(&min_stat, &deleg_cred);

	    if (verbose_flag)
		printf("checking actual mech (%s) on export/imported cred\n",
		       oid_to_string(actual_mech));
	    loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx,
		 &actual_mech2, &deleg_cred);

	    gss_release_cred(&min_stat, &deleg_cred);

	    gss_delete_sec_context(&min_stat, &cctx, NULL);
	    gss_delete_sec_context(&min_stat, &sctx, NULL);

	    /* try again using SPNEGO */
	    if (verbose_flag)
		printf("checking SPNEGO on export/imported cred\n");
	    loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx,
		 &actual_mech2, &deleg_cred);

	    gss_release_cred(&min_stat, &deleg_cred);

	    gss_delete_sec_context(&min_stat, &cctx, NULL);
	    gss_delete_sec_context(&min_stat, &sctx, NULL);

	    gss_release_cred(&min_stat, &cred2);

	} else  {
	    gss_release_cred(&min_stat, &deleg_cred);
	}

    }

    empty_release();

    krb5_free_context(context);

    return 0;
}