/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/sun_nws/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/sun_nws/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "@(#)iscsit_authclient.c 1.6 08/02/14 SMI" #include #include #include #include #include #include #include #include #include #include "chap.h" #include "iscsit_authclient.h" #include "iscsit_authglue.h" #include "radius_auth.h" void client_set_numeric_data(auth_key_block_t *keyBlock, int key_type, uint32_t numeric) { auth_key_t *p; ASSERT(key_type < AUTH_KEY_TYPE_MAX); p = &keyBlock->key[key_type]; p->value.numeric = numeric; p->present = 1; } void client_set_string_data(auth_key_block_t *keyBlock, int key_type, char *string) { auth_key_t *p; ASSERT(key_type < AUTH_KEY_TYPE_MAX); p = &keyBlock->key[key_type]; p->value.string = string; p->present = 1; } void client_set_binary_data(auth_key_block_t *keyBlock, int key_type, unsigned char *binary, unsigned int len) { auth_key_t *p; ASSERT(key_type < AUTH_KEY_TYPE_MAX); p = &keyBlock->key[key_type]; p->value.binary = binary; p->len = len; p->present = 1; } void client_get_numeric_data(auth_key_block_t *keyBlock, int key_type, uint32_t *numeric) { auth_key_t *p; ASSERT(key_type < AUTH_KEY_TYPE_MAX); p = &keyBlock->key[key_type]; *numeric = p->value.numeric; } void client_get_string_data(auth_key_block_t *keyBlock, int key_type, char **string) { auth_key_t *p; ASSERT(key_type < AUTH_KEY_TYPE_MAX); p = &keyBlock->key[key_type]; *string = p->value.string; } void client_get_binary_data(auth_key_block_t *keyBlock, int key_type, unsigned char **binary, unsigned int *len) { auth_key_t *p; ASSERT(key_type < AUTH_KEY_TYPE_MAX); p = &keyBlock->key[key_type]; *binary = p->value.binary; *len = p->len; } int client_auth_key_present(auth_key_block_t *keyBlock, int key_type) { auth_key_t *p; ASSERT(key_type < AUTH_KEY_TYPE_MAX); p = &keyBlock->key[key_type]; return (p->present != 0 ? 1 : 0); } void client_compute_chap_resp(uchar_t *resp, unsigned int chap_i, uint8_t *password, int password_len, uchar_t *chap_c, unsigned int challenge_len) { iscsi_auth_md5_context context; iscsi_auth_md5_init(&context); /* * id byte */ resp[0] = chap_i; iscsi_auth_md5_update(&context, resp, 1); /* * shared secret */ iscsi_auth_md5_update(&context, (uchar_t *)password, password_len); /* * challenge value */ iscsi_auth_md5_update(&context, chap_c, challenge_len); iscsi_auth_md5_final(resp, &context); } int client_verify_chap_resp(char *target_chap_name, char *initiator_chap_name, uint8_t *password_in, int password_in_len, unsigned int chap_i, uchar_t *chap_c, unsigned int challenge_len, uchar_t *chap_r, unsigned int resp_len) { uchar_t verifyData[iscsiAuthChapResponseLength]; iscsi_radius_props_t p_radius_cfg; /* XXX radius configuration */ const char *eastings_dot_central = "172.20.56.56"; const char *shared_secret = "target"; uint32_t ip4; inet_pton(AF_INET, eastings_dot_central, (void *)&ip4); p_radius_cfg.r_addr.u_in4.s_addr = htonl(ip4); p_radius_cfg.r_insize = sizeof (in_addr_t); p_radius_cfg.r_port = 1812; p_radius_cfg.r_shared_secret_len = strlen(shared_secret); bcopy(shared_secret, p_radius_cfg.r_shared_secret, p_radius_cfg.r_shared_secret_len); p_radius_cfg.r_radius_config_valid = B_TRUE; p_radius_cfg.r_radius_access = B_FALSE; /* Check if RADIUS access is enabled */ if (/* persistent_radius_get(&p_radius_cfg) == 0 && */ p_radius_cfg.r_radius_access == B_TRUE) { chap_validation_status_type chap_valid_status; RADIUS_CONFIG radius_cfg; if (p_radius_cfg.r_radius_config_valid == B_FALSE) { /* * Radius enabled but configuration invalid - */ return (ISCSI_AUTH_FAILED); } /* Use RADIUS server to authentication target */ if (p_radius_cfg.r_insize == sizeof (in_addr_t)) { /* IPv4 */ radius_cfg.rad_svr_addr.i_addr.in4.s_addr = p_radius_cfg.r_addr.u_in4.s_addr; radius_cfg.rad_svr_addr.i_insize = sizeof (in_addr_t); } else if (p_radius_cfg.r_insize == sizeof (in6_addr_t)) { /* IPv6 */ bcopy(p_radius_cfg.r_addr.u_in6.s6_addr, radius_cfg.rad_svr_addr.i_addr.in6.s6_addr, 16); radius_cfg.rad_svr_addr.i_insize = sizeof (in6_addr_t); } else { return (ISCSI_AUTH_FAILED); } radius_cfg.rad_svr_port = p_radius_cfg.r_port; bcopy(p_radius_cfg.r_shared_secret, radius_cfg.rad_svr_shared_secret, MAX_RAD_SHARED_SECRET_LEN); radius_cfg.rad_svr_shared_secret_len = p_radius_cfg.r_shared_secret_len; chap_valid_status = radius_chap_validate( initiator_chap_name, target_chap_name, chap_c, challenge_len, chap_r, resp_len, chap_i, radius_cfg.rad_svr_addr, radius_cfg.rad_svr_port, radius_cfg.rad_svr_shared_secret, radius_cfg.rad_svr_shared_secret_len); if (chap_valid_status == CHAP_VALIDATION_PASSED) { cmn_err(CE_NOTE, "client_verify_chap_resp: radius auth passed."); return (ISCSI_AUTH_PASSED); } cmn_err(CE_NOTE, "client_verify_chap_resp: radius auth failed."); return (ISCSI_AUTH_FAILED); } /* only MD5 is supported */ if (resp_len != sizeof (verifyData)) { return (ISCSI_AUTH_FAILED); } client_compute_chap_resp( &verifyData[0], chap_i, password_in, password_in_len, chap_c, challenge_len); if (bcmp(chap_r, verifyData, sizeof (verifyData)) != 0) { return (ISCSI_AUTH_FAILED); } /* chap response OK */ return (ISCSI_AUTH_PASSED); } void auth_random_set_data(uchar_t *data, unsigned int length) { (void) random_get_pseudo_bytes(data, length); }