Exemple #1
0
int main (int argc, char **argv)
{
	TALLOC_CTX *mem_ctx = talloc_init("ktutil");
	krb5_context context;
	krb5_keytab keytab;
	krb5_kt_cursor cursor;
	krb5_keytab_entry entry;
	krb5_error_code ret;
	char *keytab_name = NULL;

	if (mem_ctx == NULL) {
		printf("talloc_init() failed\n");
		exit(1);
	}

	if (argc != 2) {
		printf("Usage: %s KEYTAB\n", argv[0]);
		exit(1);
	}

	keytab_name = argv[1];

	initialize_krb5_error_table();

	ret = krb5_init_context(&context);
	if (ret) {
		smb_krb5_err(mem_ctx, context, 1, ret, "krb5_context");
	}

	ret = smb_krb5_open_keytab_relative(context, keytab_name, false, &keytab);
	if (ret) {
		smb_krb5_err(mem_ctx, context, 1, ret, "open keytab");
	}

	ret = krb5_kt_start_seq_get(context, keytab, &cursor);
	if (ret) {
		smb_krb5_err(mem_ctx, context, 1, ret, "krb5_kt_start_seq_get");
	}

	for (ret = krb5_kt_next_entry(context, keytab, &entry, &cursor);
	     ret == 0;
	     ret = krb5_kt_next_entry(context, keytab, &entry, &cursor))
	{
		char *principal = NULL;
		char *enctype_str = NULL;
		krb5_enctype enctype = smb_get_enctype_from_kt_entry(&entry);

		ret = smb_krb5_unparse_name(mem_ctx,
					    context,
					    entry.principal,
					    &principal);
		if (ret) {
			smb_krb5_err(mem_ctx, context, 1, ret, "krb5_enctype_to_string");
		}

		ret = smb_krb5_enctype_to_string(context,
						 enctype,
						 &enctype_str);
		if (ret) {
			smb_krb5_err(mem_ctx, context, 1, ret, "krb5_enctype_to_string");
		}

		printf("%s (%s)\n", principal, enctype_str);

		TALLOC_FREE(principal);
		SAFE_FREE(enctype_str);
		smb_krb5_kt_free_entry(context, &entry);
	}

	ret = krb5_kt_end_seq_get(context, keytab, &cursor);
	if (ret) {
		smb_krb5_err(mem_ctx, context, 1, ret, "krb5_kt_end_seq_get");
	}

	ret = krb5_kt_close(context, keytab);
	if (ret) {
		smb_krb5_err(mem_ctx, context, 1, ret, "krb5_kt_close");
	}

	krb5_free_context(context);
	talloc_free(mem_ctx);
	return 0;
}
Exemple #2
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;
}
Exemple #3
0
static bool ads_keytab_verify_ticket(krb5_context context,
					krb5_auth_context auth_context,
					const DATA_BLOB *ticket,
					krb5_ticket **pp_tkt,
					krb5_keyblock **keyblock,
					krb5_error_code *perr)
{
	krb5_error_code ret = 0;
	bool auth_ok = False;
	krb5_keytab keytab = NULL;
	krb5_kt_cursor kt_cursor;
	krb5_keytab_entry kt_entry;
	char *valid_princ_formats[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
	char *entry_princ_s = NULL;
	fstring my_name, my_fqdn;
	int i;
	int number_matched_principals = 0;
	krb5_data packet;

	*pp_tkt = NULL;
	*keyblock = NULL;
	*perr = 0;

	/* Generate the list of principal names which we expect
	 * clients might want to use for authenticating to the file
	 * service.  We allow name$,{host,cifs}/{name,fqdn,name.REALM}. */

	fstrcpy(my_name, global_myname());

	my_fqdn[0] = '\0';
	name_to_fqdn(my_fqdn, global_myname());

	if (asprintf(&valid_princ_formats[0], "%s$@%s", my_name, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[1], "host/%s@%s", my_name, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[2], "host/%s@%s", my_fqdn, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[3], "host/%s.%s@%s", my_name, lp_realm(), lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[4], "cifs/%s@%s", my_name, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[5], "cifs/%s@%s", my_fqdn, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[6], "cifs/%s.%s@%s", my_name, lp_realm(), lp_realm()) == -1) {
		goto out;
	}

	ZERO_STRUCT(kt_entry);
	ZERO_STRUCT(kt_cursor);

	ret = smb_krb5_open_keytab(context, NULL, False, &keytab);
	if (ret) {
		DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_open_keytab failed (%s)\n", error_message(ret)));
		goto out;
	}

	/* Iterate through the keytab.  For each key, if the principal
	 * name case-insensitively matches one of the allowed formats,
	 * try verifying the ticket using that principal. */

	ret = krb5_kt_start_seq_get(context, keytab, &kt_cursor);
	if (ret) {
		DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_start_seq_get failed (%s)\n", error_message(ret)));
		goto out;
	}
  
	while (!auth_ok && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) {
		ret = smb_krb5_unparse_name(context, kt_entry.principal, &entry_princ_s);
		if (ret) {
			DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s)\n",
				error_message(ret)));
			goto out;
		}

		for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {

			if (!strequal(entry_princ_s, valid_princ_formats[i])) {
				continue;
			}

			number_matched_principals++;
			packet.length = ticket->length;
			packet.data = (char *)ticket->data;
			*pp_tkt = NULL;

			ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, &packet,
							  	      kt_entry.principal, keytab,
								      NULL, pp_tkt, keyblock);

			if (ret) {
				DEBUG(10,("ads_keytab_verify_ticket: "
					"krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s\n",
					entry_princ_s, error_message(ret)));

				/* workaround for MIT: 
				* as krb5_ktfile_get_entry will explicitly
				* close the krb5_keytab as soon as krb5_rd_req
				* has successfully decrypted the ticket but the
				* ticket is not valid yet (due to clockskew)
				* there is no point in querying more keytab
				* entries - Guenther */
					
				if (ret == KRB5KRB_AP_ERR_TKT_NYV || 
				    ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
				    ret == KRB5KRB_AP_ERR_SKEW) {
					break;
				}
			} else {
				DEBUG(3,("ads_keytab_verify_ticket: "
					"krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s\n",
					entry_princ_s));
				auth_ok = True;
				break;
			}
		}

		/* Free the name we parsed. */
		SAFE_FREE(entry_princ_s);

		/* Free the entry we just read. */
		smb_krb5_kt_free_entry(context, &kt_entry);
		ZERO_STRUCT(kt_entry);
	}
	krb5_kt_end_seq_get(context, keytab, &kt_cursor);

	ZERO_STRUCT(kt_cursor);

  out:
	
	for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {
		SAFE_FREE(valid_princ_formats[i]);
	}
	
	if (!auth_ok) {
		if (!number_matched_principals) {
			DEBUG(3, ("ads_keytab_verify_ticket: no keytab principals matched expected file service name.\n"));
		} else {
			DEBUG(3, ("ads_keytab_verify_ticket: krb5_rd_req failed for all %d matched keytab principals\n",
				number_matched_principals));
		}
	}

	SAFE_FREE(entry_princ_s);

	{
		krb5_keytab_entry zero_kt_entry;
		ZERO_STRUCT(zero_kt_entry);
		if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
			smb_krb5_kt_free_entry(context, &kt_entry);
		}
	}

	{
		krb5_kt_cursor zero_csr;
		ZERO_STRUCT(zero_csr);
		if ((memcmp(&kt_cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
			krb5_kt_end_seq_get(context, keytab, &kt_cursor);
		}
	}

	if (keytab) {
		krb5_kt_close(context, keytab);
	}
	*perr = ret;
	return auth_ok;
}
Exemple #4
0
struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *ctx,
						 const char *principal,
						 int kvno,
						 const krb5_enctype enctype,
						 TALLOC_CTX *mem_ctx)
{
	krb5_error_code ret = 0;
	krb5_kt_cursor cursor;
	krb5_keytab_entry kt_entry;
	struct libnet_keytab_entry *entry = NULL;

	ZERO_STRUCT(kt_entry);
	ZERO_STRUCT(cursor);

	ret = krb5_kt_start_seq_get(ctx->context, ctx->keytab, &cursor);
	if (ret) {
		DEBUG(10, ("krb5_kt_start_seq_get failed: %s\n",
			  error_message(ret)));
		return NULL;
	}

	while (krb5_kt_next_entry(ctx->context, ctx->keytab, &kt_entry, &cursor) == 0)
	{
		krb5_keyblock *keyp;
		char *princ_s = NULL;

		entry = NULL;

		if (kt_entry.vno != kvno) {
			goto cont;
		}

		keyp = KRB5_KT_KEY(&kt_entry);

		if (KRB5_KEY_TYPE(keyp) != enctype) {
			goto cont;
		}

		entry = talloc_zero(mem_ctx, struct libnet_keytab_entry);
		if (!entry) {
			DEBUG(3, ("talloc failed\n"));
			goto fail;
		}

		ret = smb_krb5_unparse_name(entry, ctx->context, kt_entry.principal,
					    &princ_s);
		if (ret) {
			goto cont;
		}

		if (strcmp(principal, princ_s) != 0) {
			goto cont;
		}

		entry->principal = talloc_strdup(entry, princ_s);
		if (!entry->principal) {
			DEBUG(3, ("talloc_strdup_failed\n"));
			goto fail;
		}

		entry->name = talloc_move(entry, &princ_s);

		entry->password = data_blob_talloc(entry, KRB5_KEY_DATA(keyp),
						   KRB5_KEY_LENGTH(keyp));
		if (!entry->password.data) {
			DEBUG(3, ("data_blob_talloc failed\n"));
			goto fail;
		}

		DEBUG(10, ("found entry\n"));

		smb_krb5_kt_free_entry(ctx->context, &kt_entry);
		break;

fail:
		smb_krb5_kt_free_entry(ctx->context, &kt_entry);
		TALLOC_FREE(entry);
		break;

cont:
		smb_krb5_kt_free_entry(ctx->context, &kt_entry);
		TALLOC_FREE(entry);
		continue;
	}

	krb5_kt_end_seq_get(ctx->context, ctx->keytab, &cursor);
	return entry;
}
Exemple #5
0
/**
 * Remove all entries that have the given principal, kvno and enctype.
 */
static krb5_error_code libnet_keytab_remove_entries(krb5_context context,
						    krb5_keytab keytab,
						    const char *principal,
						    int kvno,
						    const krb5_enctype enctype,
						    bool ignore_kvno)
{
	krb5_error_code ret;
	krb5_kt_cursor cursor;
	krb5_keytab_entry kt_entry;

	ZERO_STRUCT(kt_entry);
	ZERO_STRUCT(cursor);

	ret = krb5_kt_start_seq_get(context, keytab, &cursor);
	if (ret) {
		return 0;
	}

	while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0)
	{
		krb5_keyblock *keyp;
		char *princ_s = NULL;

		if (kt_entry.vno != kvno && !ignore_kvno) {
			goto cont;
		}

		keyp = KRB5_KT_KEY(&kt_entry);

		if (KRB5_KEY_TYPE(keyp) != enctype) {
			goto cont;
		}

		ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal,
					    &princ_s);
		if (ret) {
			DEBUG(5, ("smb_krb5_unparse_name failed (%s)\n",
				  error_message(ret)));
			goto cont;
		}

		if (strcmp(principal, princ_s) != 0) {
			goto cont;
		}

		/* match found - remove */

		DEBUG(10, ("found entry for principal %s, kvno %d, "
			   "enctype %d - trying to remove it\n",
			   princ_s, kt_entry.vno, KRB5_KEY_TYPE(keyp)));

		ret = krb5_kt_end_seq_get(context, keytab, &cursor);
		ZERO_STRUCT(cursor);
		if (ret) {
			DEBUG(5, ("krb5_kt_end_seq_get failed (%s)\n",
				  error_message(ret)));
			goto cont;
		}

		ret = krb5_kt_remove_entry(context, keytab,
					   &kt_entry);
		if (ret) {
			DEBUG(5, ("krb5_kt_remove_entry failed (%s)\n",
				  error_message(ret)));
			goto cont;
		}
		DEBUG(10, ("removed entry for principal %s, kvno %d, "
			   "enctype %d\n", princ_s, kt_entry.vno,
			   KRB5_KEY_TYPE(keyp)));

		ret = krb5_kt_start_seq_get(context, keytab, &cursor);
		if (ret) {
			DEBUG(5, ("krb5_kt_start_seq_get failed (%s)\n",
				  error_message(ret)));
			goto cont;
		}

cont:
		smb_krb5_kt_free_entry(context, &kt_entry);
		TALLOC_FREE(princ_s);
	}

	ret = krb5_kt_end_seq_get(context, keytab, &cursor);
	if (ret) {
		DEBUG(5, ("krb5_kt_end_seq_get failed (%s)\n",
			  error_message(ret)));
	}

	return ret;
}
Exemple #6
0
static krb5_error_code ads_keytab_verify_for_principal(krb5_context context,
					krb5_auth_context   auth_context,
					const krb5_keytab_entry * kt_entry,
					const DATA_BLOB *   ticket,
					const char *	    svc_principal,
					krb5_ticket **	    pp_tkt,
					krb5_keyblock **    keyblock)
{
	krb5_error_code ret = 0;
	krb5_keytab keytab = NULL;
	krb5_data   packet;
	char *	    entry_princ_s = NULL;

	ret = krb5_kt_default(context, &keytab);
	if (ret) {
		DEBUG(1, ("ads_keytab_verify_for_principal: krb5_kt_default failed (%s)\n", error_message(ret)));
		goto out;
	}

	ret = smb_krb5_unparse_name(context, kt_entry->principal, &entry_princ_s);
	if (ret) {
		DEBUG(1, ("ads_keytab_verify_for_principal: smb_krb5_unparse_name failed (%s)\n",
			error_message(ret)));
		goto out;
	}

	if (!strequal(entry_princ_s, svc_principal)) {
		ret = KRB5KRB_AP_ERR_BADMATCH;
		goto out;
	}

	packet.length = ticket->length;
	packet.data = (char *)ticket->data;
	*pp_tkt = NULL;

	ret = krb5_rd_req_return_keyblock_from_keytab(context,
				&auth_context, &packet,
				kt_entry, keytab,
				pp_tkt, keyblock);

	if (ret) {
		DEBUG(3,("ads_keytab_verify_for_principal: "
			    "failed for principal %s: %s\n",
			entry_princ_s, error_message(ret)));
		goto out;
	}


	DEBUG(3,("ads_keytab_verify_for_principal: succeeded for principal %s\n",
		entry_princ_s));

out:
	/* Free the name we parsed. */
	SAFE_FREE(entry_princ_s);

	if (keytab) {
		krb5_kt_close(context, keytab);
		keytab = NULL;
	}

	return ret;
}
Exemple #7
0
static krb5_error_code
get_key_from_keytab(krb5_context context,
		    krb5_const_principal server,
		    krb5_enctype enctype,
		    krb5_kvno kvno,
		    krb5_keyblock **out_key)
{
	krb5_keytab_entry entry;
	krb5_error_code ret;
	krb5_keytab keytab;
	char *name = NULL;

	/* We have to open a new keytab handle here, as MIT does
	   an implicit open/getnext/close on krb5_kt_get_entry. We
	   may be in the middle of a keytab enumeration when this is
	   called. JRA. */

	ret = krb5_kt_default(context, &keytab);
	if (ret) {
		DEBUG(0,("get_key_from_keytab: failed to open keytab: %s\n", error_message(ret)));
		return ret;
	}

	if ( DEBUGLEVEL >= 10 ) {
		if (smb_krb5_unparse_name(context, server, &name) == 0) {
			DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n", 
				kvno, enctype, name));
			SAFE_FREE(name);
		}
	}

	ret = krb5_kt_get_entry(context,
				keytab,
				server,
				kvno,
				enctype,
				&entry);

	if (ret) {
		DEBUG(0,("get_key_from_keytab: failed to retrieve key: %s\n", error_message(ret)));
		goto out;
	}

#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
	ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);
#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) /* MIT */
	ret = krb5_copy_keyblock(context, &entry.key, out_key);
#else
#error UNKNOWN_KRB5_KEYTAB_ENTRY_FORMAT
#endif

	if (ret) {
		DEBUG(0,("get_key_from_keytab: failed to copy key: %s\n", error_message(ret)));
		goto out;
	}
		
	smb_krb5_kt_free_entry(context, &entry);
	
out:    
	krb5_kt_close(context, keytab);
	return ret;
}
Exemple #8
0
/* does the ccache have a valid TGT? */
static time_t
get_tgt_time(const char *ccname) {
	krb5_context context;
	krb5_ccache ccache;
	krb5_cc_cursor cur;
	krb5_creds creds;
	krb5_principal principal;
	time_t credtime = 0;
	char *realm = NULL;
	TALLOC_CTX *mem_ctx;

	if (krb5_init_context(&context)) {
		syslog(LOG_DEBUG, "%s: unable to init krb5 context", __func__);
		return 0;
	}

	if (krb5_cc_resolve(context, ccname, &ccache)) {
		syslog(LOG_DEBUG, "%s: unable to resolve krb5 cache", __func__);
		goto err_cache;
	}

	if (krb5_cc_set_flags(context, ccache, 0)) {
		syslog(LOG_DEBUG, "%s: unable to set flags", __func__);
		goto err_cache;
	}

	if (krb5_cc_get_principal(context, ccache, &principal)) {
		syslog(LOG_DEBUG, "%s: unable to get principal", __func__);
		goto err_princ;
	}

	if (krb5_cc_start_seq_get(context, ccache, &cur)) {
		syslog(LOG_DEBUG, "%s: unable to seq start", __func__);
		goto err_ccstart;
	}

	if ((realm = smb_krb5_principal_get_realm(context, principal)) == NULL) {
		syslog(LOG_DEBUG, "%s: unable to get realm", __func__);
		goto err_ccstart;
	}

	mem_ctx = talloc_init("cifs.upcall");
	while (!credtime && !krb5_cc_next_cred(context, ccache, &cur, &creds)) {
		char *name;
		if (smb_krb5_unparse_name(mem_ctx, context, creds.server, &name)) {
			syslog(LOG_DEBUG, "%s: unable to unparse name", __func__);
			goto err_endseq;
		}
		if (krb5_realm_compare(context, creds.server, principal) &&
		    strnequal(name, KRB5_TGS_NAME, KRB5_TGS_NAME_SIZE) &&
		    strnequal(name+KRB5_TGS_NAME_SIZE+1, realm, strlen(realm)) &&
		    creds.times.endtime > time(NULL))
			credtime = creds.times.endtime;
                krb5_free_cred_contents(context, &creds);
		TALLOC_FREE(name);
        }
err_endseq:
	TALLOC_FREE(mem_ctx);
        krb5_cc_end_seq_get(context, ccache, &cur);
err_ccstart:
	krb5_free_principal(context, principal);
err_princ:
#if defined(KRB5_TC_OPENCLOSE)
	krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
#endif
	krb5_cc_close(context, ccache);
err_cache:
	krb5_free_context(context);
	return credtime;
}