1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
231a1a84a3SPeter Dunlap * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24fcf3ce44SJohn Forte * Use is subject to license terms.
25fcf3ce44SJohn Forte *
26fcf3ce44SJohn Forte * iSCSI Pseudo HBA Driver
27fcf3ce44SJohn Forte */
28fcf3ce44SJohn Forte
29fcf3ce44SJohn Forte #include <sys/random.h>
30fcf3ce44SJohn Forte
31fcf3ce44SJohn Forte #include "chap.h"
32fcf3ce44SJohn Forte #include "iscsi.h"
331a1a84a3SPeter Dunlap #include <sys/iscsi_protocol.h>
34fcf3ce44SJohn Forte #include "iscsiAuthClient.h"
35fcf3ce44SJohn Forte #include "persistent.h"
36fcf3ce44SJohn Forte
37fcf3ce44SJohn Forte /*
38fcf3ce44SJohn Forte * Authenticate a target's CHAP response.
39fcf3ce44SJohn Forte *
40fcf3ce44SJohn Forte * username - Incoming username from the the target.
41fcf3ce44SJohn Forte * responseData - Incoming response data from the target.
42fcf3ce44SJohn Forte */
43fcf3ce44SJohn Forte int
iscsiAuthClientChapAuthRequest(IscsiAuthClient * client,char * username,unsigned int id,uchar_t * challengeData,unsigned int challengeLength,uchar_t * responseData,unsigned int responseLength)44fcf3ce44SJohn Forte iscsiAuthClientChapAuthRequest(IscsiAuthClient *client,
45fcf3ce44SJohn Forte char *username, unsigned int id, uchar_t *challengeData,
46fcf3ce44SJohn Forte unsigned int challengeLength, uchar_t *responseData,
47fcf3ce44SJohn Forte unsigned int responseLength)
48fcf3ce44SJohn Forte {
49fcf3ce44SJohn Forte iscsi_sess_t *isp = (iscsi_sess_t *)client->userHandle;
50fcf3ce44SJohn Forte IscsiAuthMd5Context context;
51fcf3ce44SJohn Forte uchar_t verifyData[16];
52fcf3ce44SJohn Forte iscsi_radius_props_t p_radius_cfg;
53fcf3ce44SJohn Forte
54fcf3ce44SJohn Forte if (isp == NULL) {
55fcf3ce44SJohn Forte return (iscsiAuthStatusFail);
56fcf3ce44SJohn Forte }
57fcf3ce44SJohn Forte
58fcf3ce44SJohn Forte /*
59fcf3ce44SJohn Forte * the expected credentials are in the session
60fcf3ce44SJohn Forte */
61fcf3ce44SJohn Forte if (strcmp(username, isp->sess_auth.username_in) != 0) {
62fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi session(%u) failed authentication, "
63fcf3ce44SJohn Forte "received incorrect username from target",
64fcf3ce44SJohn Forte isp->sess_oid);
65fcf3ce44SJohn Forte return (iscsiAuthStatusFail);
66fcf3ce44SJohn Forte }
67fcf3ce44SJohn Forte
68fcf3ce44SJohn Forte /* Check if RADIUS access is enabled */
69fcf3ce44SJohn Forte if (persistent_radius_get(&p_radius_cfg) == ISCSI_NVFILE_SUCCESS &&
70fcf3ce44SJohn Forte p_radius_cfg.r_radius_access == B_TRUE) {
71fcf3ce44SJohn Forte chap_validation_status_type chap_valid_status;
72fcf3ce44SJohn Forte int authStatus;
73fcf3ce44SJohn Forte RADIUS_CONFIG radius_cfg;
74fcf3ce44SJohn Forte
75fcf3ce44SJohn Forte if (p_radius_cfg.r_radius_config_valid == B_FALSE) {
76fcf3ce44SJohn Forte /*
77fcf3ce44SJohn Forte * Radius enabled but configuration invalid -
78fcf3ce44SJohn Forte * invalid condition
79fcf3ce44SJohn Forte */
80fcf3ce44SJohn Forte return (iscsiAuthStatusFail);
81fcf3ce44SJohn Forte }
82fcf3ce44SJohn Forte
83fcf3ce44SJohn Forte /* Use RADIUS server to authentication target */
84fcf3ce44SJohn Forte if (p_radius_cfg.r_insize == sizeof (in_addr_t)) {
85fcf3ce44SJohn Forte /* IPv4 */
86fcf3ce44SJohn Forte radius_cfg.rad_svr_addr.i_addr.in4.s_addr =
87fcf3ce44SJohn Forte p_radius_cfg.r_addr.u_in4.s_addr;
88fcf3ce44SJohn Forte radius_cfg.rad_svr_addr.i_insize
89fcf3ce44SJohn Forte = sizeof (in_addr_t);
90fcf3ce44SJohn Forte } else if (p_radius_cfg.r_insize == sizeof (in6_addr_t)) {
91fcf3ce44SJohn Forte /* IPv6 */
92fcf3ce44SJohn Forte bcopy(p_radius_cfg.r_addr.u_in6.s6_addr,
93fcf3ce44SJohn Forte radius_cfg.rad_svr_addr.i_addr.in6.s6_addr,
94fcf3ce44SJohn Forte 16);
95fcf3ce44SJohn Forte radius_cfg.rad_svr_addr.i_insize = sizeof (in6_addr_t);
96fcf3ce44SJohn Forte } else {
97fcf3ce44SJohn Forte return (iscsiAuthStatusFail);
98fcf3ce44SJohn Forte }
99fcf3ce44SJohn Forte
100fcf3ce44SJohn Forte radius_cfg.rad_svr_port = p_radius_cfg.r_port;
101fcf3ce44SJohn Forte bcopy(p_radius_cfg.r_shared_secret,
102fcf3ce44SJohn Forte radius_cfg.rad_svr_shared_secret,
103fcf3ce44SJohn Forte MAX_RAD_SHARED_SECRET_LEN);
104fcf3ce44SJohn Forte radius_cfg.rad_svr_shared_secret_len =
105fcf3ce44SJohn Forte p_radius_cfg.r_shared_secret_len;
106fcf3ce44SJohn Forte
107fcf3ce44SJohn Forte /* Entry point to the CHAP authentication module. */
108*5df5713fSbing zhao - Sun Microsystems - Beijing China chap_valid_status = chap_validate_tgt(
109*5df5713fSbing zhao - Sun Microsystems - Beijing China isp->sess_auth.username_in,
110*5df5713fSbing zhao - Sun Microsystems - Beijing China isp->sess_auth.username,
111*5df5713fSbing zhao - Sun Microsystems - Beijing China challengeData,
112*5df5713fSbing zhao - Sun Microsystems - Beijing China challengeLength,
113*5df5713fSbing zhao - Sun Microsystems - Beijing China responseData,
114*5df5713fSbing zhao - Sun Microsystems - Beijing China responseLength,
115*5df5713fSbing zhao - Sun Microsystems - Beijing China id,
116*5df5713fSbing zhao - Sun Microsystems - Beijing China RADIUS_AUTHENTICATION,
117*5df5713fSbing zhao - Sun Microsystems - Beijing China (void *)&radius_cfg);
118fcf3ce44SJohn Forte
119fcf3ce44SJohn Forte switch (chap_valid_status) {
120fcf3ce44SJohn Forte case CHAP_VALIDATION_PASSED:
121fcf3ce44SJohn Forte authStatus = iscsiAuthStatusPass;
122fcf3ce44SJohn Forte break;
123fcf3ce44SJohn Forte case CHAP_VALIDATION_INVALID_RESPONSE:
124fcf3ce44SJohn Forte authStatus = iscsiAuthStatusFail;
125fcf3ce44SJohn Forte break;
126fcf3ce44SJohn Forte case CHAP_VALIDATION_DUP_SECRET:
127fcf3ce44SJohn Forte authStatus = iscsiAuthStatusFail;
128fcf3ce44SJohn Forte break;
129fcf3ce44SJohn Forte case CHAP_VALIDATION_RADIUS_ACCESS_ERROR:
130fcf3ce44SJohn Forte authStatus = iscsiAuthStatusFail;
131fcf3ce44SJohn Forte break;
132fcf3ce44SJohn Forte case CHAP_VALIDATION_BAD_RADIUS_SECRET:
133fcf3ce44SJohn Forte authStatus = iscsiAuthStatusFail;
134fcf3ce44SJohn Forte break;
135fcf3ce44SJohn Forte default:
136fcf3ce44SJohn Forte authStatus = iscsiAuthStatusFail;
137fcf3ce44SJohn Forte break;
138fcf3ce44SJohn Forte }
139fcf3ce44SJohn Forte return (authStatus);
140fcf3ce44SJohn Forte } else {
141fcf3ce44SJohn Forte /* Use target secret (if defined) to authenticate target */
142fcf3ce44SJohn Forte if ((isp->sess_auth.password_length_in < 1) ||
143fcf3ce44SJohn Forte (isp->sess_auth.password_in[0] == '\0')) {
144fcf3ce44SJohn Forte /* No target secret defined - invalid condition */
145fcf3ce44SJohn Forte return (iscsiAuthStatusFail);
146fcf3ce44SJohn Forte }
147fcf3ce44SJohn Forte
148fcf3ce44SJohn Forte /*
149fcf3ce44SJohn Forte * challenge length is I->T, and shouldn't need to
150fcf3ce44SJohn Forte * be checked
151fcf3ce44SJohn Forte */
152fcf3ce44SJohn Forte if (responseLength != sizeof (verifyData)) {
153fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi session(%u) failed "
154fcf3ce44SJohn Forte "authentication, received incorrect CHAP response "
155fcf3ce44SJohn Forte "from target", isp->sess_oid);
156fcf3ce44SJohn Forte return (iscsiAuthStatusFail);
157fcf3ce44SJohn Forte }
158fcf3ce44SJohn Forte
159fcf3ce44SJohn Forte iscsiAuthMd5Init(&context);
160fcf3ce44SJohn Forte
161fcf3ce44SJohn Forte /*
162fcf3ce44SJohn Forte * id byte
163fcf3ce44SJohn Forte */
164fcf3ce44SJohn Forte verifyData[0] = id;
165fcf3ce44SJohn Forte iscsiAuthMd5Update(&context, verifyData, 1);
166fcf3ce44SJohn Forte
167fcf3ce44SJohn Forte /*
168fcf3ce44SJohn Forte * shared secret
169fcf3ce44SJohn Forte */
170fcf3ce44SJohn Forte iscsiAuthMd5Update(&context,
171fcf3ce44SJohn Forte (uchar_t *)isp->sess_auth.password_in,
172fcf3ce44SJohn Forte isp->sess_auth.password_length_in);
173fcf3ce44SJohn Forte
174fcf3ce44SJohn Forte /*
175fcf3ce44SJohn Forte * challenge value
176fcf3ce44SJohn Forte */
177fcf3ce44SJohn Forte iscsiAuthMd5Update(&context,
178fcf3ce44SJohn Forte (uchar_t *)challengeData,
179fcf3ce44SJohn Forte challengeLength);
180fcf3ce44SJohn Forte
181fcf3ce44SJohn Forte iscsiAuthMd5Final(verifyData, &context);
182fcf3ce44SJohn Forte
183fcf3ce44SJohn Forte if (bcmp(responseData, verifyData,
184fcf3ce44SJohn Forte sizeof (verifyData)) == 0) {
185fcf3ce44SJohn Forte return (iscsiAuthStatusPass);
186fcf3ce44SJohn Forte }
187fcf3ce44SJohn Forte
188fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi session(%u) failed authentication, "
189fcf3ce44SJohn Forte "received incorrect CHAP response from target",
190fcf3ce44SJohn Forte isp->sess_oid);
191fcf3ce44SJohn Forte }
192fcf3ce44SJohn Forte
193fcf3ce44SJohn Forte return (iscsiAuthStatusFail);
194fcf3ce44SJohn Forte }
195fcf3ce44SJohn Forte
196fcf3ce44SJohn Forte /* ARGSUSED */
197fcf3ce44SJohn Forte void
iscsiAuthClientChapAuthCancel(IscsiAuthClient * client)198fcf3ce44SJohn Forte iscsiAuthClientChapAuthCancel(IscsiAuthClient * client)
199fcf3ce44SJohn Forte {
200fcf3ce44SJohn Forte }
201fcf3ce44SJohn Forte
202fcf3ce44SJohn Forte
203fcf3ce44SJohn Forte int
iscsiAuthClientTextToNumber(const char * text,unsigned long * pNumber)204fcf3ce44SJohn Forte iscsiAuthClientTextToNumber(const char *text, unsigned long *pNumber)
205fcf3ce44SJohn Forte {
206fcf3ce44SJohn Forte char *pEnd;
207fcf3ce44SJohn Forte unsigned long number;
208fcf3ce44SJohn Forte
209fcf3ce44SJohn Forte if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) {
210fcf3ce44SJohn Forte if (ddi_strtoul(text + 2, &pEnd, 16, &number) != 0) {
211fcf3ce44SJohn Forte return (1); /* Error */
212fcf3ce44SJohn Forte }
213fcf3ce44SJohn Forte } else {
214fcf3ce44SJohn Forte if (ddi_strtoul(text, &pEnd, 10, &number) != 0) {
215fcf3ce44SJohn Forte return (1); /* Error */
216fcf3ce44SJohn Forte }
217fcf3ce44SJohn Forte }
218fcf3ce44SJohn Forte
219fcf3ce44SJohn Forte if (*text != '\0' && *pEnd == '\0') {
220fcf3ce44SJohn Forte *pNumber = number;
221fcf3ce44SJohn Forte return (0); /* No error */
222fcf3ce44SJohn Forte } else {
223fcf3ce44SJohn Forte return (1); /* Error */
224fcf3ce44SJohn Forte }
225fcf3ce44SJohn Forte }
226fcf3ce44SJohn Forte
227fcf3ce44SJohn Forte /* ARGSUSED */
228fcf3ce44SJohn Forte void
iscsiAuthClientNumberToText(unsigned long number,char * text,unsigned int length)229fcf3ce44SJohn Forte iscsiAuthClientNumberToText(unsigned long number, char *text,
230fcf3ce44SJohn Forte unsigned int length)
231fcf3ce44SJohn Forte {
232fcf3ce44SJohn Forte (void) sprintf(text, "%lu", number);
233fcf3ce44SJohn Forte }
234fcf3ce44SJohn Forte
235fcf3ce44SJohn Forte
236fcf3ce44SJohn Forte void
iscsiAuthRandomSetData(uchar_t * data,unsigned int length)237fcf3ce44SJohn Forte iscsiAuthRandomSetData(uchar_t *data, unsigned int length)
238fcf3ce44SJohn Forte {
239fcf3ce44SJohn Forte (void) random_get_pseudo_bytes(data, length);
240fcf3ce44SJohn Forte }
241fcf3ce44SJohn Forte
242fcf3ce44SJohn Forte
243fcf3ce44SJohn Forte void
iscsiAuthMd5Init(IscsiAuthMd5Context * context)244fcf3ce44SJohn Forte iscsiAuthMd5Init(IscsiAuthMd5Context * context)
245fcf3ce44SJohn Forte {
246fcf3ce44SJohn Forte MD5Init(context);
247fcf3ce44SJohn Forte }
248fcf3ce44SJohn Forte
249fcf3ce44SJohn Forte
250fcf3ce44SJohn Forte void
iscsiAuthMd5Update(IscsiAuthMd5Context * context,uchar_t * data,unsigned int length)251fcf3ce44SJohn Forte iscsiAuthMd5Update(IscsiAuthMd5Context *context, uchar_t *data,
252fcf3ce44SJohn Forte unsigned int length)
253fcf3ce44SJohn Forte {
254fcf3ce44SJohn Forte MD5Update(context, data, length);
255fcf3ce44SJohn Forte }
256fcf3ce44SJohn Forte
257fcf3ce44SJohn Forte
258fcf3ce44SJohn Forte void
iscsiAuthMd5Final(uchar_t * hash,IscsiAuthMd5Context * context)259fcf3ce44SJohn Forte iscsiAuthMd5Final(uchar_t *hash, IscsiAuthMd5Context *context)
260fcf3ce44SJohn Forte {
261fcf3ce44SJohn Forte MD5Final(hash, context);
262fcf3ce44SJohn Forte }
263fcf3ce44SJohn Forte
264fcf3ce44SJohn Forte
265fcf3ce44SJohn Forte int
iscsiAuthClientData(uchar_t * outData,unsigned int * outLength,uchar_t * inData,unsigned int inLength)266fcf3ce44SJohn Forte iscsiAuthClientData(uchar_t *outData, unsigned int *outLength,
267fcf3ce44SJohn Forte uchar_t *inData, unsigned int inLength)
268fcf3ce44SJohn Forte {
269fcf3ce44SJohn Forte if (*outLength < inLength) {
270fcf3ce44SJohn Forte return (1); /* error */
271fcf3ce44SJohn Forte }
272fcf3ce44SJohn Forte bcopy(inData, outData, inLength);
273fcf3ce44SJohn Forte *outLength = inLength;
274fcf3ce44SJohn Forte return (0); /* no error */
275fcf3ce44SJohn Forte }
276