예제 #1
0
파일: srv_keytab.c 프로젝트: hef/samba
static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
                                     const char *samAccountName,
                                     const char *realm,
                                     const char *saltPrincipal,
                                     int kvno,
                                     const char *new_secret,
                                     const char *old_secret,
                                     uint32_t supp_enctypes,
                                     krb5_principal *principals,
                                     krb5_context context,
                                     krb5_keytab keytab,
                                     bool add_old,
                                     const char **error_string)
{
    krb5_error_code ret;
    krb5_principal salt_princ = NULL;
    krb5_enctype *enctypes;
    TALLOC_CTX *mem_ctx;

    if (!new_secret) {
        /* There is no password here, so nothing to do */
        return 0;
    }

    mem_ctx = talloc_new(parent_ctx);
    if (!mem_ctx) {
        *error_string = talloc_strdup(parent_ctx,
                                      "unable to allocate tmp_ctx for create_keytab");
        return ENOMEM;
    }

    /* The salt used to generate these entries may be different however,
     * fetch that */
    ret = salt_principal(mem_ctx, samAccountName, realm, saltPrincipal,
                         context, &salt_princ, error_string);
    if (ret) {
        talloc_free(mem_ctx);
        return ret;
    }

    ret = ms_suptypes_to_ietf_enctypes(mem_ctx, supp_enctypes, &enctypes);
    if (ret) {
        *error_string = talloc_asprintf(parent_ctx,
                                        "create_keytab: generating list of "
                                        "encryption types failed (%s)\n",
                                        smb_get_krb5_error_message(context,
                                                ret, mem_ctx));
        goto done;
    }

    ret = keytab_add_keys(mem_ctx, principals,
                          salt_princ, kvno, new_secret,
                          context, enctypes, keytab, error_string);
    if (ret) {
        talloc_steal(parent_ctx, *error_string);
        goto done;
    }

    if (old_secret && add_old && kvno != 0) {
        ret = keytab_add_keys(mem_ctx, principals,
                              salt_princ, kvno - 1, old_secret,
                              context, enctypes, keytab, error_string);
        if (ret) {
            talloc_steal(parent_ctx, *error_string);
        }
    }

done:
    krb5_free_principal(context, salt_princ);
    talloc_free(mem_ctx);
    return ret;
}
예제 #2
0
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;
}