--- /dev/null Fri Apr 4 13:31:04 2008 +++ new/src/sun_nws/comstar/port_providers/iscsit/src/iscsit_authclient.c Fri Apr 4 13:31:04 2008 @@ -0,0 +1,279 @@ +/* + * 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); +}