示例#1
0
static krb5_error_code libnet_keytab_add_entry(krb5_context context,
					       krb5_keytab keytab,
					       krb5_kvno kvno,
					       const char *princ_s,
					       krb5_enctype enctype,
					       krb5_data password)
{
	krb5_keyblock *keyp;
	krb5_keytab_entry kt_entry;
	krb5_error_code ret;

	/* remove duplicates first ... */
	ret = libnet_keytab_remove_entries(context, keytab, princ_s, kvno,
					   enctype, false);
	if (ret) {
		DEBUG(1, ("libnet_keytab_remove_entries failed: %s\n",
			  error_message(ret)));
	}

	ZERO_STRUCT(kt_entry);

	kt_entry.vno = kvno;

	ret = smb_krb5_parse_name(context, princ_s, &kt_entry.principal);
	if (ret) {
		DEBUG(1, ("smb_krb5_parse_name(%s) failed (%s)\n",
			  princ_s, error_message(ret)));
		return ret;
	}

	keyp = KRB5_KT_KEY(&kt_entry);

	if (create_kerberos_key_from_string(context, kt_entry.principal,
					    &password, keyp, enctype, true))
	{
		ret = KRB5KRB_ERR_GENERIC;
		goto done;
	}

	ret = krb5_kt_add_entry(context, keytab, &kt_entry);
	if (ret) {
		DEBUG(1, ("adding entry to keytab failed (%s)\n",
			  error_message(ret)));
	}

done:
	krb5_free_keyblock_contents(context, keyp);
	krb5_free_principal(context, kt_entry.principal);
	ZERO_STRUCT(kt_entry);
	smb_krb5_kt_free_entry(context, &kt_entry);

	return ret;
}
示例#2
0
static krb5_error_code ads_secrets_verify_ticket(krb5_context context,
						krb5_auth_context auth_context,
						krb5_principal host_princ,
						const DATA_BLOB *ticket,
						krb5_ticket **pp_tkt,
						krb5_keyblock **keyblock,
						krb5_error_code *perr)
{
	krb5_error_code ret = 0;
	bool auth_ok = False;
	char *password_s = NULL;
	krb5_data password;
	krb5_enctype enctypes[] = { 
#if defined(ENCTYPE_ARCFOUR_HMAC)
		ENCTYPE_ARCFOUR_HMAC,
#endif
		ENCTYPE_DES_CBC_CRC, 
		ENCTYPE_DES_CBC_MD5, 
		ENCTYPE_NULL
	};
	krb5_data packet;
	int i;

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


	if (!secrets_init()) {
		DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
		*perr = KRB5_CONFIG_CANTOPEN;
		return False;
	}

	password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
	if (!password_s) {
		DEBUG(1,("ads_secrets_verify_ticket: failed to fetch machine password\n"));
		*perr = KRB5_LIBOS_CANTREADPWD;
		return False;
	}

	password.data = password_s;
	password.length = strlen(password_s);

	/* CIFS doesn't use addresses in tickets. This would break NAT. JRA */

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

	/* We need to setup a auth context with each possible encoding type in turn. */
	for (i=0;enctypes[i];i++) {
		krb5_keyblock *key = NULL;

		if (!(key = SMB_MALLOC_P(krb5_keyblock))) {
			ret = ENOMEM;
			goto out;
		}
	
		if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i], false)) {
			SAFE_FREE(key);
			continue;
		}

		krb5_auth_con_setuseruserkey(context, auth_context, key);

		if (!(ret = krb5_rd_req(context, &auth_context, &packet, 
					NULL,
					NULL, NULL, pp_tkt))) {
			DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n",
				(unsigned int)enctypes[i] ));
			auth_ok = True;
			krb5_copy_keyblock(context, key, keyblock);
			krb5_free_keyblock(context, key);
			break;
		}

		DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
				("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
				(unsigned int)enctypes[i], error_message(ret)));

		/* successfully decrypted but ticket is just not valid at the moment */
		if (ret == KRB5KRB_AP_ERR_TKT_NYV || 
		    ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
		    ret == KRB5KRB_AP_ERR_SKEW) {
			krb5_free_keyblock(context, key);
			break;
		}

		krb5_free_keyblock(context, key);

	}

 out:
	SAFE_FREE(password_s);
	*perr = ret;
	return auth_ok;
}
示例#3
0
static krb5_error_code ads_secrets_verify_ticket(krb5_context context,
						krb5_auth_context auth_context,
						krb5_principal host_princ,
						const DATA_BLOB *ticket,
						krb5_ticket **pp_tkt,
						krb5_keyblock **keyblock,
						krb5_error_code *perr)
{
	krb5_error_code ret = 0;
	bool auth_ok = False;
	bool cont = true;
	char *password_s = NULL;
	/* Let's make some room for 2 password (old and new)*/
	krb5_data passwords[2];
	krb5_enctype enctypes[] = {
#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
		ENCTYPE_AES256_CTS_HMAC_SHA1_96,
#endif
#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
		ENCTYPE_AES128_CTS_HMAC_SHA1_96,
#endif
		ENCTYPE_ARCFOUR_HMAC,
		ENCTYPE_DES_CBC_CRC,
		ENCTYPE_DES_CBC_MD5,
		ENCTYPE_NULL
	};
	krb5_data packet;
	int i, j;

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

	ZERO_STRUCT(passwords);

	if (!secrets_init()) {
		DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
		*perr = KRB5_CONFIG_CANTOPEN;
		return False;
	}

	password_s = secrets_fetch_machine_password(lp_workgroup(),
						    NULL, NULL);
	if (!password_s) {
		DEBUG(1,(__location__ ": failed to fetch machine password\n"));
		*perr = KRB5_LIBOS_CANTREADPWD;
		return False;
	}

	passwords[0].data = password_s;
	passwords[0].length = strlen(password_s);

	password_s = secrets_fetch_prev_machine_password(lp_workgroup());
	if (password_s) {
		DEBUG(10, (__location__ ": found previous password\n"));
		passwords[1].data = password_s;
		passwords[1].length = strlen(password_s);
	}

	/* CIFS doesn't use addresses in tickets. This would break NAT. JRA */

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

	/* We need to setup a auth context with each possible encoding type
	 * in turn. */
	for (j=0; j<2 && passwords[j].length; j++) {

		for (i=0;enctypes[i];i++) {
			krb5_keyblock *key = NULL;

			if (!(key = SMB_MALLOC_P(krb5_keyblock))) {
				ret = ENOMEM;
				goto out;
			}

			if (create_kerberos_key_from_string(context,
						host_princ, &passwords[j],
						key, enctypes[i], false)) {
				SAFE_FREE(key);
				continue;
			}

			krb5_auth_con_setuseruserkey(context,
							auth_context, key);

			if (!(ret = krb5_rd_req(context, &auth_context,
						&packet, NULL, NULL,
						NULL, pp_tkt))) {
				DEBUG(10, (__location__ ": enc type [%u] "
					   "decrypted message !\n",
					   (unsigned int)enctypes[i]));
				auth_ok = True;
				cont = false;
				krb5_copy_keyblock(context, key, keyblock);
				krb5_free_keyblock(context, key);
				break;
			}

			DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
				(__location__ ": enc type [%u] failed to "
				 "decrypt with error %s\n",
				 (unsigned int)enctypes[i],
				 error_message(ret)));

			/* successfully decrypted but ticket is just not
			 * valid at the moment */
			if (ret == KRB5KRB_AP_ERR_TKT_NYV ||
			    ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
			    ret == KRB5KRB_AP_ERR_SKEW) {
				krb5_free_keyblock(context, key);
				cont = false;
				break;
			}

			krb5_free_keyblock(context, key);
		}
		if (!cont) {
			/* If we found a valid pass then no need to try
			 * the next one or we have invalid ticket so no need
			 * to try next password*/
			break;
		}
	}

 out:
	SAFE_FREE(passwords[0].data);
	SAFE_FREE(passwords[1].data);
	*perr = ret;
	return auth_ok;
}
示例#4
0
static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
				       const char *princ_string,
				       krb5_principal princ,
				       krb5_principal salt_princ,
				       int kvno,
				       const char *password_s,
				       struct smb_krb5_context *smb_krb5_context,
				       const char **enctype_strings,
				       krb5_keytab keytab)
{
	int i;
	krb5_error_code ret;
	krb5_data password;
	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
	if (!mem_ctx) {
		return ENOMEM;
	}

	password.data = discard_const_p(char *, password_s);
	password.length = strlen(password_s);

	for (i=0; enctype_strings[i]; i++) {
		krb5_keytab_entry entry;
		krb5_enctype enctype;
		ret = krb5_string_to_enctype(smb_krb5_context->krb5_context, enctype_strings[i], &enctype);
		if (ret != 0) {
			DEBUG(1, ("Failed to interpret %s as a krb5 encryption type: %s\n",				  
				  enctype_strings[i],
				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
							     ret, mem_ctx)));
			talloc_free(mem_ctx);
			return ret;
		}
		ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context, 
						      salt_princ, &password, &entry.keyblock, enctype);
		if (ret != 0) {
			talloc_free(mem_ctx);
			return ret;
		}

                entry.principal = princ;
                entry.vno       = kvno;
		ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
		if (ret != 0) {
			DEBUG(1, ("Failed to add %s entry for %s(kvno %d) to keytab: %s\n",
				  enctype_strings[i],
				  princ_string,
				  kvno,
				  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 (%s)\n", 
			  princ_string, kvno,
			  enctype_strings[i]));
		
		krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
	}
	talloc_free(mem_ctx);
	return 0;
}