xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/iscsi/iscsiAuthClientGlue.c (revision d036a205252fb571ad98bf872416a3d413d75f82)
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