⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kerberos_util.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
static int create_keytab(TALLOC_CTX *parent_ctx,			 struct cli_credentials *machine_account,			 struct smb_krb5_context *smb_krb5_context,			 const char **enctype_strings,			 krb5_keytab keytab,			 bool add_old) {	krb5_error_code ret;	const char *password_s;	const char *old_secret;	int kvno;	krb5_principal salt_princ;	krb5_principal princ;	const char *princ_string;	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);	if (!mem_ctx) {		return ENOMEM;	}	princ_string = cli_credentials_get_principal(machine_account, mem_ctx);	/* Get the principal we will store the new keytab entries under */	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);	if (ret) {		DEBUG(1,("create_keytab: makeing krb5 principal failed (%s)\n",			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 						    ret, mem_ctx)));		talloc_free(mem_ctx);		return ret;	}	/* The salt used to generate these entries may be different however, fetch that */	ret = salt_principal_from_credentials(mem_ctx, machine_account, 					      smb_krb5_context, 					      &salt_princ);	if (ret) {		DEBUG(1,("create_keytab: makeing salt principal failed (%s)\n",			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 						    ret, mem_ctx)));		talloc_free(mem_ctx);		return ret;	}	/* Finally, do the dance to get the password to put in the entry */	password_s = cli_credentials_get_password(machine_account);	if (!password_s) {		krb5_keytab_entry entry;		const struct samr_Password *mach_pwd;		if (!str_list_check(enctype_strings, "arcfour-hmac-md5")) {			DEBUG(1, ("Asked to create keytab, but with only an NT hash supplied, "				  "but not listing arcfour-hmac-md5 as an enc type to include in the keytab!\n"));			talloc_free(mem_ctx);			return EINVAL;		}		/* If we don't have the plaintext password, try for		 * the MD4 password hash */		mach_pwd = cli_credentials_get_nt_hash(machine_account, mem_ctx);		if (!mach_pwd) {			/* OK, nothing to do here */			talloc_free(mem_ctx);			return 0;		}		ret = krb5_keyblock_init(smb_krb5_context->krb5_context,					 ETYPE_ARCFOUR_HMAC_MD5,					 mach_pwd->hash, sizeof(mach_pwd->hash), 					 &entry.keyblock);		if (ret) {			DEBUG(1, ("create_keytab: krb5_keyblock_init failed: %s\n",				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 							     ret, mem_ctx)));			talloc_free(mem_ctx);			return ret;		}		entry.principal = princ;		entry.vno       = cli_credentials_get_kvno(machine_account);		ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);		if (ret) {			DEBUG(1, ("Failed to add ARCFOUR_HMAC (only) entry for %s to keytab: %s",				  cli_credentials_get_principal(machine_account, mem_ctx), 				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 							     ret, mem_ctx)));			talloc_free(mem_ctx);			krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);			return ret;		}				DEBUG(5, ("Added %s(kvno %d) to keytab (arcfour-hmac-md5)\n", 			  cli_credentials_get_principal(machine_account, mem_ctx),			  cli_credentials_get_kvno(machine_account)));		krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);		/* Can't go any further, we only have this one key */		talloc_free(mem_ctx);		return 0;	}		kvno = cli_credentials_get_kvno(machine_account);	/* good, we actually have the real plaintext */	ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ, 			      kvno, password_s, smb_krb5_context, 			      enctype_strings, keytab);	if (!ret) {		talloc_free(mem_ctx);		return ret;	}	if (!add_old || kvno == 0) {		talloc_free(mem_ctx);		return 0;	}	old_secret = cli_credentials_get_old_password(machine_account);	if (!old_secret) {		talloc_free(mem_ctx);		return 0;	}		ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ, 			      kvno - 1, old_secret, smb_krb5_context, 			      enctype_strings, keytab);	if (!ret) {		talloc_free(mem_ctx);		return ret;	}	talloc_free(mem_ctx);	return 0;}/* * Walk the keytab, looking for entries of this principal name, with KVNO other than current kvno -1. * * These entries are now stale, we only keep the current, and previous entries around. * * Inspired by the code in Samba3 for 'use kerberos keytab'. * */static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,					  struct cli_credentials *machine_account,					  struct smb_krb5_context *smb_krb5_context,					  krb5_keytab keytab, bool *found_previous){	krb5_error_code ret, ret2;	krb5_kt_cursor cursor;	krb5_principal princ;	int kvno;	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);	const char *princ_string;	if (!mem_ctx) {		return ENOMEM;	}	*found_previous = false;	princ_string = cli_credentials_get_principal(machine_account, mem_ctx);	/* Get the principal we will store the new keytab entries under */	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);	if (ret) {		DEBUG(1,("update_keytab: makeing krb5 principal failed (%s)\n",			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 						    ret, mem_ctx)));		talloc_free(mem_ctx);		return ret;	}	kvno = cli_credentials_get_kvno(machine_account);	/* for each entry in the keytab */	ret = krb5_kt_start_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);	switch (ret) {	case 0:		break;	case HEIM_ERR_OPNOTSUPP:	case ENOENT:	case KRB5_KT_END:		/* no point enumerating if there isn't anything here */		talloc_free(mem_ctx);		return 0;	default:		DEBUG(1,("failed to open keytab for read of old entries: %s\n",			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 						    ret, mem_ctx)));		talloc_free(mem_ctx);		return ret;	}	while (!ret) {		krb5_keytab_entry entry;		ret = krb5_kt_next_entry(smb_krb5_context->krb5_context, keytab, &entry, &cursor);		if (ret) {			break;		}		/* if it matches our principal */		if (!krb5_kt_compare(smb_krb5_context->krb5_context, &entry, princ, 0, 0)) {			/* Free the entry, it wasn't the one we were looking for anyway */			krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);			continue;		}		/* delete it, if it is not kvno -1 */		if (entry.vno != (kvno - 1 )) {			/* Release the enumeration.  We are going to			 * have to start this from the top again,			 * because deletes during enumeration may not			 * always be consistant.			 *			 * Also, the enumeration locks a FILE: keytab			 */					krb5_kt_end_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);			ret = krb5_kt_remove_entry(smb_krb5_context->krb5_context, keytab, &entry);			krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);			/* Deleted: Restart from the top */			ret2 = krb5_kt_start_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);			if (ret2) {				krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);				DEBUG(1,("failed to restart enumeration of keytab: %s\n",					 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 								    ret, mem_ctx)));								talloc_free(mem_ctx);				return ret2;			}			if (ret) {				break;			}					} else {			*found_previous = true;		}				/* Free the entry, we don't need it any more */		krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);					}	krb5_kt_end_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);	switch (ret) {	case 0:		break;	case ENOENT:	case KRB5_KT_END:		ret = 0;		break;	default:		DEBUG(1,("failed in deleting old entries for principal: %s: %s\n",			 princ_string, 			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 						    ret, mem_ctx)));	}	talloc_free(mem_ctx);	return ret;}int smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,			   struct cli_credentials *machine_account,			   struct smb_krb5_context *smb_krb5_context,			   const char **enctype_strings,			   struct keytab_container *keytab_container) {	krb5_error_code ret;	bool found_previous;	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);	if (!mem_ctx) {		return ENOMEM;	}	ret = remove_old_entries(mem_ctx, machine_account, 				 smb_krb5_context, keytab_container->keytab, &found_previous);	if (ret != 0) {		talloc_free(mem_ctx);		return ret;	}		/* Create a new keytab.  If during the cleanout we found	 * entires for kvno -1, then don't try and duplicate them.	 * Otherwise, add kvno, and kvno -1 */		ret = create_keytab(mem_ctx, machine_account, smb_krb5_context, 			    enctype_strings, 			    keytab_container->keytab, 			    found_previous ? false : true);	talloc_free(mem_ctx);	return ret;}int smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,					   struct cli_credentials *machine_account,					   struct smb_krb5_context *smb_krb5_context,					   const char **enctype_strings,					   struct keytab_container **keytab_container) {	krb5_error_code ret;	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);	const char *rand_string;	const char *keytab_name;	if (!mem_ctx) {		return ENOMEM;	}		*keytab_container = talloc(mem_ctx, struct keytab_container);	rand_string = generate_random_str(mem_ctx, 16);	if (!rand_string) {		talloc_free(mem_ctx);		return ENOMEM;	}	keytab_name = talloc_asprintf(mem_ctx, "MEMORY:%s", 				      rand_string);	if (!keytab_name) {		talloc_free(mem_ctx);		return ENOMEM;	}	ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context, keytab_name, keytab_container);	if (ret) {		return ret;	}	ret = smb_krb5_update_keytab(mem_ctx, machine_account, smb_krb5_context, enctype_strings, *keytab_container);	if (ret == 0) {		talloc_steal(parent_ctx, *keytab_container);	} else {		*keytab_container = NULL;	}	talloc_free(mem_ctx);	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -