示例#1
0
static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state)
{
	if (!gensec_krb5_state->smb_krb5_context) {
		/* We can't clean anything else up unless we started up this far */
		return 0;
	}
	if (gensec_krb5_state->enc_ticket.length) { 
		kerberos_free_data_contents(gensec_krb5_state->smb_krb5_context->krb5_context, 
					    &gensec_krb5_state->enc_ticket); 
	}

	if (gensec_krb5_state->ticket) {
		krb5_free_ticket(gensec_krb5_state->smb_krb5_context->krb5_context, 
				 gensec_krb5_state->ticket);
	}

	/* ccache freed in a child destructor */

	krb5_free_keyblock(gensec_krb5_state->smb_krb5_context->krb5_context, 
			   gensec_krb5_state->keyblock);
		
	if (gensec_krb5_state->auth_context) {
		krb5_auth_con_free(gensec_krb5_state->smb_krb5_context->krb5_context, 
				   gensec_krb5_state->auth_context);
	}

	return 0;
}
示例#2
0
static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
{
	krb5_context context = NULL;
	krb5_error_code kerr = 0;
	krb5_data reply;
	krb5_principal host_princ = NULL;
	char *host_princ_s = NULL;
	BOOL ret = False;

	*pblob_out = data_blob(NULL,0);

	initialize_krb5_error_table();
	kerr = krb5_init_context(&context);
	if (kerr) {
		return False;
	}
	/* Create server principal. */
	asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
	if (!host_princ_s) {
		goto out;
	}
	strlower_m(host_princ_s);

	kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
	if (kerr) {
		DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
			host_princ_s, error_message(kerr) ));
		goto out;
	}
	
	kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
	if (kerr) {
		DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
			error_message(kerr) ));
		goto out;
	}

	*pblob_out = data_blob(reply.data, reply.length);
	kerberos_free_data_contents(context,&reply);
	ret = True;

  out:

	if (host_princ_s) {
		SAFE_FREE(host_princ_s);
	}
	if (host_princ) {
		krb5_free_principal(context, host_princ);
	}
	krb5_free_context(context);
	return ret;
}
示例#3
0
NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
			   const char *realm,
			   time_t time_offset,
			   const DATA_BLOB *ticket,
			   char **principal,
			   struct PAC_DATA **pac_data,
			   DATA_BLOB *ap_rep,
			   DATA_BLOB *session_key,
			   bool use_replay_cache)
{
	NTSTATUS sret = NT_STATUS_LOGON_FAILURE;
	NTSTATUS pac_ret;
	DATA_BLOB auth_data;
	krb5_context context = NULL;
	krb5_auth_context auth_context = NULL;
	krb5_data packet;
	krb5_ticket *tkt = NULL;
	krb5_rcache rcache = NULL;
	krb5_keyblock *keyblock = NULL;
	time_t authtime;
	krb5_error_code ret = 0;
	int flags = 0;	
	krb5_principal host_princ = NULL;
	krb5_const_principal client_principal = NULL;
	char *host_princ_s = NULL;
	bool auth_ok = False;
	bool got_auth_data = False;
	struct named_mutex *mutex = NULL;

	ZERO_STRUCT(packet);
	ZERO_STRUCT(auth_data);

	*principal = NULL;
	*pac_data = NULL;
	*ap_rep = data_blob_null;
	*session_key = data_blob_null;

	initialize_krb5_error_table();
	ret = krb5_init_context(&context);
	if (ret) {
		DEBUG(1,("ads_verify_ticket: krb5_init_context failed (%s)\n", error_message(ret)));
		return NT_STATUS_LOGON_FAILURE;
	}

	if (time_offset != 0) {
		krb5_set_real_time(context, time(NULL) + time_offset, 0);
	}

	ret = krb5_set_default_realm(context, realm);
	if (ret) {
		DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret)));
		goto out;
	}

	/* This whole process is far more complex than I would
           like. We have to go through all this to allow us to store
           the secret internally, instead of using /etc/krb5.keytab */

	ret = krb5_auth_con_init(context, &auth_context);
	if (ret) {
		DEBUG(1,("ads_verify_ticket: krb5_auth_con_init failed (%s)\n", error_message(ret)));
		goto out;
	}

	krb5_auth_con_getflags( context, auth_context, &flags );
	if ( !use_replay_cache ) {
		/* Disable default use of a replay cache */
		flags &= ~KRB5_AUTH_CONTEXT_DO_TIME;
		krb5_auth_con_setflags( context, auth_context, flags );
	}

	if (asprintf(&host_princ_s, "%s$", global_myname()) == -1) {
		goto out;
	}

	strlower_m(host_princ_s);
	ret = smb_krb5_parse_name(context, host_princ_s, &host_princ);
	if (ret) {
		DEBUG(1,("ads_verify_ticket: smb_krb5_parse_name(%s) failed (%s)\n",
					host_princ_s, error_message(ret)));
		goto out;
	}


	if ( use_replay_cache ) {
		
		/* Lock a mutex surrounding the replay as there is no 
		   locking in the MIT krb5 code surrounding the replay 
		   cache... */

		mutex = grab_named_mutex(talloc_tos(), "replay cache mutex",
					 10);
		if (mutex == NULL) {
			DEBUG(1,("ads_verify_ticket: unable to protect "
				 "replay cache with mutex.\n"));
			ret = KRB5_CC_IO;
			goto out;
		}

		/* JRA. We must set the rcache here. This will prevent 
		   replay attacks. */
		
		ret = krb5_get_server_rcache(context, 
					     krb5_princ_component(context, host_princ, 0), 
					     &rcache);
		if (ret) {
			DEBUG(1,("ads_verify_ticket: krb5_get_server_rcache "
				 "failed (%s)\n", error_message(ret)));
			goto out;
		}

		ret = krb5_auth_con_setrcache(context, auth_context, rcache);
		if (ret) {
			DEBUG(1,("ads_verify_ticket: krb5_auth_con_setrcache "
				 "failed (%s)\n", error_message(ret)));
			goto out;
		}
	}

	/* Try secrets.tdb first and fallback to the krb5.keytab if
	   necessary */

	auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ,
					    ticket, &tkt, &keyblock, &ret);

	if (!auth_ok &&
	    (ret == KRB5KRB_AP_ERR_TKT_NYV ||
	     ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
	     ret == KRB5KRB_AP_ERR_SKEW)) {
		goto auth_failed;
	}

	if (!auth_ok && lp_use_kerberos_keytab()) {
		auth_ok = ads_keytab_verify_ticket(context, auth_context, 
						   ticket, &tkt, &keyblock, &ret);
	}

	if ( use_replay_cache ) {		
		TALLOC_FREE(mutex);
#if 0
		/* Heimdal leaks here, if we fix the leak, MIT crashes */
		if (rcache) {
			krb5_rc_close(context, rcache);
		}
#endif
	}	

 auth_failed:
	if (!auth_ok) {
		DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", 
			 error_message(ret)));
		/* Try map the error return in case it's something like
		 * a clock skew error.
		 */
		sret = krb5_to_nt_status(ret);
		if (NT_STATUS_IS_OK(sret) || NT_STATUS_EQUAL(sret,NT_STATUS_UNSUCCESSFUL)) {
			sret = NT_STATUS_LOGON_FAILURE;
		}
		DEBUG(10,("ads_verify_ticket: returning error %s\n",
			nt_errstr(sret) ));
		goto out;
	} 
	
	authtime = get_authtime_from_tkt(tkt);
	client_principal = get_principal_from_tkt(tkt);

	ret = krb5_mk_rep(context, auth_context, &packet);
	if (ret) {
		DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",
			error_message(ret)));
		goto out;
	}

	*ap_rep = data_blob(packet.data, packet.length);
	if (packet.data) {
		kerberos_free_data_contents(context, &packet);
		ZERO_STRUCT(packet);
	}

	get_krb5_smb_session_key(context, auth_context, session_key, True);
	dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length);

#if 0
	file_save("/tmp/ticket.dat", ticket->data, ticket->length);
#endif

	/* continue when no PAC is retrieved or we couldn't decode the PAC 
	   (like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set, or
	   Kerberos tickets encrypted using a DES key) - Guenther */

	got_auth_data = get_auth_data_from_tkt(mem_ctx, &auth_data, tkt);
	if (!got_auth_data) {
		DEBUG(3,("ads_verify_ticket: did not retrieve auth data. continuing without PAC\n"));
	}

	if (got_auth_data) {
		pac_ret = decode_pac_data(mem_ctx, &auth_data, context, keyblock, client_principal, authtime, pac_data);
		if (!NT_STATUS_IS_OK(pac_ret)) {
			DEBUG(3,("ads_verify_ticket: failed to decode PAC_DATA: %s\n", nt_errstr(pac_ret)));
			*pac_data = NULL;
		}
		data_blob_free(&auth_data);
	}

#if 0
#if defined(HAVE_KRB5_TKT_ENC_PART2)
	/* MIT */
	if (tkt->enc_part2) {
		file_save("/tmp/authdata.dat",
			  tkt->enc_part2->authorization_data[0]->contents,
			  tkt->enc_part2->authorization_data[0]->length);
	}
#else
	/* Heimdal */
	if (tkt->ticket.authorization_data) {
		file_save("/tmp/authdata.dat",
			  tkt->ticket.authorization_data->val->ad_data.data,
			  tkt->ticket.authorization_data->val->ad_data.length);
	}
#endif
#endif

	if ((ret = smb_krb5_unparse_name(context, client_principal, principal))) {
		DEBUG(3,("ads_verify_ticket: smb_krb5_unparse_name failed (%s)\n", 
			 error_message(ret)));
		sret = NT_STATUS_LOGON_FAILURE;
		goto out;
	}

	sret = NT_STATUS_OK;

 out:

	TALLOC_FREE(mutex);

	if (!NT_STATUS_IS_OK(sret)) {
		data_blob_free(&auth_data);
	}

	if (!NT_STATUS_IS_OK(sret)) {
		data_blob_free(ap_rep);
	}

	if (host_princ) {
		krb5_free_principal(context, host_princ);
	}

	if (keyblock) {
		krb5_free_keyblock(context, keyblock);
	}

	if (tkt != NULL) {
		krb5_free_ticket(context, tkt);
	}

	SAFE_FREE(host_princ_s);

	if (auth_context) {
		krb5_auth_con_free(context, auth_context);
	}

	if (context) {
		krb5_free_context(context);
	}

	return sret;
}
示例#4
0
ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *principal,
				 const char *newpw, int time_offset)
{

	ADS_STATUS aret;
	krb5_error_code ret = 0;
	krb5_context context = NULL;
	krb5_principal princ = NULL;
	krb5_ccache ccache = NULL;
	int result_code;
	krb5_data result_code_string = { 0 };
	krb5_data result_string = { 0 };

	initialize_krb5_error_table();
	ret = krb5_init_context(&context);
	if (ret) {
		DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
		return ADS_ERROR_KRB5(ret);
	}

	if (principal) {
		ret = smb_krb5_parse_name(context, principal, &princ);
		if (ret) {
			krb5_free_context(context);
			DEBUG(1, ("Failed to parse %s (%s)\n", principal,
				  error_message(ret)));
			return ADS_ERROR_KRB5(ret);
		}
	}

	if (time_offset != 0) {
		krb5_set_real_time(context, time(NULL) + time_offset, 0);
	}

	ret = krb5_cc_default(context, &ccache);
	if (ret) {
		krb5_free_principal(context, princ);
	        krb5_free_context(context);
		DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
		return ADS_ERROR_KRB5(ret);
	}

	ret = krb5_set_password_using_ccache(context,
					     ccache,
					     discard_const_p(char, newpw),
					     princ,
					     &result_code,
					     &result_code_string,
					     &result_string);
	if (ret) {
		DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret)));
		aret = ADS_ERROR_KRB5(ret);
		goto done;
	}

	if (result_code != KRB5_KPASSWD_SUCCESS) {
		ret = kpasswd_err_to_krb5_err(result_code);
		DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret)));
		aret = ADS_ERROR_KRB5(ret);
		goto done;
	}

	aret = ADS_SUCCESS;

done:
	kerberos_free_data_contents(context, &result_code_string);
	kerberos_free_data_contents(context, &result_string);
	krb5_free_principal(context, princ);
	krb5_cc_close(context, ccache);
	krb5_free_context(context);

	return aret;
}
示例#5
0
static ADS_STATUS ads_krb5_chg_password(const char *kdc_host,
					const char *principal,
					const char *oldpw, 
					const char *newpw, 
					int time_offset)
{
    ADS_STATUS aret;
    krb5_error_code ret;
    krb5_context context = NULL;
    krb5_principal princ;
    krb5_get_init_creds_opt opts;
    krb5_creds creds;
    char *chpw_princ = NULL, *password;
    char *realm = NULL;
    int result_code;
    krb5_data result_code_string = { 0 };
    krb5_data result_string = { 0 };
    smb_krb5_addresses *addr = NULL;

    initialize_krb5_error_table();
    ret = krb5_init_context(&context);
    if (ret) {
	DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
	return ADS_ERROR_KRB5(ret);
    }

    if ((ret = smb_krb5_parse_name(context, principal,
                                    &princ))) {
	krb5_free_context(context);
	DEBUG(1,("Failed to parse %s (%s)\n", principal, error_message(ret)));
	return ADS_ERROR_KRB5(ret);
    }

    krb5_get_init_creds_opt_init(&opts);

    krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
    krb5_get_init_creds_opt_set_renew_life(&opts, 0);
    krb5_get_init_creds_opt_set_forwardable(&opts, 0);
    krb5_get_init_creds_opt_set_proxiable(&opts, 0);

    /* note that heimdal will fill in the local addresses if the addresses
     * in the creds_init_opt are all empty and then later fail with invalid
     * address, sending our local netbios krb5 address - just like windows
     * - avoids this - gd */
    ret = smb_krb5_gen_netbios_krb5_address(&addr, lp_netbios_name());
    if (ret) {
        krb5_free_principal(context, princ);
        krb5_free_context(context);
        return ADS_ERROR_KRB5(ret);
    }
    krb5_get_init_creds_opt_set_address_list(&opts, addr->addrs);

    realm = smb_krb5_principal_get_realm(context, princ);

    /* We have to obtain an INITIAL changepw ticket for changing password */
    if (asprintf(&chpw_princ, "kadmin/changepw@%s", realm) == -1) {
	krb5_free_context(context);
	free(realm);
	DEBUG(1,("ads_krb5_chg_password: asprintf fail\n"));
	return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
    }

    free(realm);
    password = SMB_STRDUP(oldpw);
    ret = krb5_get_init_creds_password(context, &creds, princ, password,
					   kerb_prompter, NULL, 
					   0, chpw_princ, &opts);
    SAFE_FREE(chpw_princ);
    SAFE_FREE(password);

    if (ret) {
      if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
	DEBUG(1,("Password incorrect while getting initial ticket"));
      else
	DEBUG(1,("krb5_get_init_creds_password failed (%s)\n", error_message(ret)));

	krb5_free_principal(context, princ);
	krb5_free_context(context);
	return ADS_ERROR_KRB5(ret);
    }

    ret = krb5_change_password(context,
			       &creds,
			       discard_const_p(char, newpw),
			       &result_code,
			       &result_code_string,
			       &result_string);
    if (ret) {
	DEBUG(1, ("krb5_change_password failed (%s)\n", error_message(ret)));
	aret = ADS_ERROR_KRB5(ret);
	goto done;
    }

    if (result_code != KRB5_KPASSWD_SUCCESS) {
	ret = kpasswd_err_to_krb5_err(result_code);
	DEBUG(1, ("krb5_change_password failed (%s)\n", error_message(ret)));
	aret = ADS_ERROR_KRB5(ret);
	goto done;
    }

    aret = ADS_SUCCESS;

done:
    kerberos_free_data_contents(context, &result_code_string);
    kerberos_free_data_contents(context, &result_string);
    krb5_free_principal(context, princ);
    krb5_free_context(context);

    return aret;
}
示例#6
0
static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security,
					 TALLOC_CTX *mem_ctx,
					 struct auth_session_info **_session_info) 
{
	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
	struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
	krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
	struct auth_session_info *session_info = NULL;

	krb5_principal client_principal;
	char *principal_string;
	
	DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
	krb5_data pac_data;

	krb5_error_code ret;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}
	
	ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);
	if (ret) {
		DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", 
			  smb_get_krb5_error_message(context, 
						     ret, tmp_ctx)));
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	
	ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context, 
				client_principal, &principal_string);
	if (ret) {
		DEBUG(1, ("Unable to parse client principal: %s\n",
			  smb_get_krb5_error_message(context, 
						     ret, tmp_ctx)));
		krb5_free_principal(context, client_principal);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	ret = krb5_ticket_get_authorization_data_type(context, gensec_krb5_state->ticket, 
						      KRB5_AUTHDATA_WIN2K_PAC, 
						      &pac_data);
	
	if (ret) {
		/* NO pac */
		DEBUG(5, ("krb5_ticket_get_authorization_data_type failed to find PAC: %s\n", 
			  smb_get_krb5_error_message(context, 
						     ret, tmp_ctx)));
	} else {
		/* Found pac */
		pac_blob = data_blob_talloc(tmp_ctx, pac_data.data, pac_data.length);
		kerberos_free_data_contents(context, &pac_data);
		if (!pac_blob.data) {
			free(principal_string);
			krb5_free_principal(context, client_principal);
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		/* decode and verify the pac */
		nt_status = kerberos_decode_pac(gensec_krb5_state,
						pac_blob,
						gensec_krb5_state->smb_krb5_context->krb5_context,
						NULL, gensec_krb5_state->keyblock,
						client_principal,
						gensec_krb5_state->ticket->ticket.authtime, NULL);

		if (!NT_STATUS_IS_OK(nt_status)) {
			free(principal_string);
			krb5_free_principal(context, client_principal);
			talloc_free(tmp_ctx);
			return nt_status;
		}

		pac_blob_ptr = &pac_blob;
	}

	nt_status = gensec_generate_session_info_pac(tmp_ctx,
						     gensec_security,
						     gensec_krb5_state->smb_krb5_context,
						     pac_blob_ptr, principal_string,
						     gensec_get_remote_address(gensec_security),
						     &session_info);

	free(principal_string);
	krb5_free_principal(context, client_principal);

	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = gensec_krb5_session_key(gensec_security, session_info, &session_info->session_key);

	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	*_session_info = talloc_steal(mem_ctx, session_info);

	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}
示例#7
0
krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx,
					     krb5_pac pac,
					     krb5_context context,
					     struct auth_user_info_dc **user_info_dc,
					     struct PAC_SIGNATURE_DATA *pac_srv_sig,
					     struct PAC_SIGNATURE_DATA *pac_kdc_sig)
{
	NTSTATUS nt_status;
	enum ndr_err_code ndr_err;
	krb5_error_code ret;

	DATA_BLOB pac_logon_info_in, pac_srv_checksum_in, pac_kdc_checksum_in;
	krb5_data k5pac_logon_info_in, k5pac_srv_checksum_in, k5pac_kdc_checksum_in;

	union PAC_INFO info;
	struct auth_user_info_dc *user_info_dc_out;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);

	if (!tmp_ctx) {
		return ENOMEM;
	}

	ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_LOGON_INFO, &k5pac_logon_info_in);
	if (ret != 0) {
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	pac_logon_info_in = data_blob_const(k5pac_logon_info_in.data, k5pac_logon_info_in.length);

	ndr_err = ndr_pull_union_blob(&pac_logon_info_in, tmp_ctx, &info,
				      PAC_TYPE_LOGON_INFO,
				      (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
	kerberos_free_data_contents(context, &k5pac_logon_info_in);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !info.logon_info.info) {
		nt_status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	/* Pull this right into the normal auth sysstem structures */
	nt_status = make_user_info_dc_pac(mem_ctx,
					 info.logon_info.info,
					 &user_info_dc_out);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	if (pac_srv_sig) {
		ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_SRV_CHECKSUM, &k5pac_srv_checksum_in);
		if (ret != 0) {
			talloc_free(tmp_ctx);
			return ret;
		}

		pac_srv_checksum_in = data_blob_const(k5pac_srv_checksum_in.data, k5pac_srv_checksum_in.length);

		ndr_err = ndr_pull_struct_blob(&pac_srv_checksum_in, pac_srv_sig,
					       pac_srv_sig,
					       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
		kerberos_free_data_contents(context, &k5pac_srv_checksum_in);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			nt_status = ndr_map_error2ntstatus(ndr_err);
			DEBUG(0,("can't parse the KDC signature: %s\n",
				 nt_errstr(nt_status)));
			return EINVAL;
		}
	}

	if (pac_kdc_sig) {
		ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_KDC_CHECKSUM, &k5pac_kdc_checksum_in);
		if (ret != 0) {
			talloc_free(tmp_ctx);
			return ret;
		}

		pac_kdc_checksum_in = data_blob_const(k5pac_kdc_checksum_in.data, k5pac_kdc_checksum_in.length);

		ndr_err = ndr_pull_struct_blob(&pac_kdc_checksum_in, pac_kdc_sig,
					       pac_kdc_sig,
					       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
		kerberos_free_data_contents(context, &k5pac_kdc_checksum_in);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			nt_status = ndr_map_error2ntstatus(ndr_err);
			DEBUG(0,("can't parse the KDC signature: %s\n",
				 nt_errstr(nt_status)));
			return EINVAL;
		}
	}
	*user_info_dc = user_info_dc_out;

	return 0;
}
示例#8
0
/*
  get a kerberos5 ticket for the given service 
*/
int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
			DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, 
			uint32 extra_ap_opts, const char *ccname, 
			time_t *tgs_expire)

{
	krb5_error_code retval;
	krb5_data packet;
	krb5_context context = NULL;
	krb5_ccache ccdef = NULL;
	krb5_auth_context auth_context = NULL;
	krb5_enctype enc_types[] = {
#ifdef ENCTYPE_ARCFOUR_HMAC
		ENCTYPE_ARCFOUR_HMAC,
#endif 
		ENCTYPE_DES_CBC_MD5, 
		ENCTYPE_DES_CBC_CRC, 
		ENCTYPE_NULL};

	initialize_krb5_error_table();
	retval = krb5_init_context(&context);
	if (retval) {
		DEBUG(1,("cli_krb5_get_ticket: krb5_init_context failed (%s)\n", 
			 error_message(retval)));
		goto failed;
	}

	if (time_offset != 0) {
		krb5_set_real_time(context, time(NULL) + time_offset, 0);
	}

	if ((retval = krb5_cc_resolve(context, ccname ?
			ccname : krb5_cc_default_name(context), &ccdef))) {
		DEBUG(1,("cli_krb5_get_ticket: krb5_cc_default failed (%s)\n",
			 error_message(retval)));
		goto failed;
	}

	if ((retval = krb5_set_default_tgs_ktypes(context, enc_types))) {
		DEBUG(1,("cli_krb5_get_ticket: krb5_set_default_tgs_ktypes failed (%s)\n",
			 error_message(retval)));
		goto failed;
	}

	if ((retval = ads_krb5_mk_req(context, 
					&auth_context, 
					AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts,
					principal,
					ccdef, &packet,
					tgs_expire))) {
		goto failed;
	}

	get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);

	*ticket = data_blob(packet.data, packet.length);

 	kerberos_free_data_contents(context, &packet); 

failed:

	if ( context ) {
		if (ccdef)
			krb5_cc_close(context, ccdef);
		if (auth_context)
			krb5_auth_con_free(context, auth_context);
		krb5_free_context(context);
	}
		
	return retval;
}