login.c revision 270137
1/*-
2 * Copyright (c) 2012 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Edward Tomasz Napierala under sponsorship
6 * from the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: stable/10/usr.sbin/ctld/login.c 270137 2014-08-18 16:06:04Z mav $
30 */
31
32#include <assert.h>
33#include <stdbool.h>
34#include <stdint.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <unistd.h>
39#include <netinet/in.h>
40#include <openssl/err.h>
41#include <openssl/md5.h>
42#include <openssl/rand.h>
43
44#include "ctld.h"
45#include "iscsi_proto.h"
46
47static void login_send_error(struct pdu *request,
48    char class, char detail);
49
50static void
51login_set_nsg(struct pdu *response, int nsg)
52{
53	struct iscsi_bhs_login_response *bhslr;
54
55	assert(nsg == BHSLR_STAGE_SECURITY_NEGOTIATION ||
56	    nsg == BHSLR_STAGE_OPERATIONAL_NEGOTIATION ||
57	    nsg == BHSLR_STAGE_FULL_FEATURE_PHASE);
58
59	bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs;
60
61	bhslr->bhslr_flags &= 0xFC;
62	bhslr->bhslr_flags |= nsg;
63}
64
65static int
66login_csg(const struct pdu *request)
67{
68	struct iscsi_bhs_login_request *bhslr;
69
70	bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
71
72	return ((bhslr->bhslr_flags & 0x0C) >> 2);
73}
74
75static void
76login_set_csg(struct pdu *response, int csg)
77{
78	struct iscsi_bhs_login_response *bhslr;
79
80	assert(csg == BHSLR_STAGE_SECURITY_NEGOTIATION ||
81	    csg == BHSLR_STAGE_OPERATIONAL_NEGOTIATION ||
82	    csg == BHSLR_STAGE_FULL_FEATURE_PHASE);
83
84	bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs;
85
86	bhslr->bhslr_flags &= 0xF3;
87	bhslr->bhslr_flags |= csg << 2;
88}
89
90static struct pdu *
91login_receive(struct connection *conn, bool initial)
92{
93	struct pdu *request;
94	struct iscsi_bhs_login_request *bhslr;
95
96	request = pdu_new(conn);
97	pdu_receive(request);
98	if ((request->pdu_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) !=
99	    ISCSI_BHS_OPCODE_LOGIN_REQUEST) {
100		/*
101		 * The first PDU in session is special - if we receive any PDU
102		 * different than login request, we have to drop the connection
103		 * without sending response ("A target receiving any PDU
104		 * except a Login request before the Login Phase is started MUST
105		 * immediately terminate the connection on which the PDU
106		 * was received.")
107		 */
108		if (initial == false)
109			login_send_error(request, 0x02, 0x0b);
110		log_errx(1, "protocol error: received invalid opcode 0x%x",
111		    request->pdu_bhs->bhs_opcode);
112	}
113	bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
114	/*
115	 * XXX: Implement the C flag some day.
116	 */
117	if ((bhslr->bhslr_flags & BHSLR_FLAGS_CONTINUE) != 0) {
118		login_send_error(request, 0x03, 0x00);
119		log_errx(1, "received Login PDU with unsupported \"C\" flag");
120	}
121	if (bhslr->bhslr_version_max != 0x00) {
122		login_send_error(request, 0x02, 0x05);
123		log_errx(1, "received Login PDU with unsupported "
124		    "Version-max 0x%x", bhslr->bhslr_version_max);
125	}
126	if (bhslr->bhslr_version_min != 0x00) {
127		login_send_error(request, 0x02, 0x05);
128		log_errx(1, "received Login PDU with unsupported "
129		    "Version-min 0x%x", bhslr->bhslr_version_min);
130	}
131	if (ntohl(bhslr->bhslr_cmdsn) < conn->conn_cmdsn) {
132		login_send_error(request, 0x02, 0x05);
133		log_errx(1, "received Login PDU with decreasing CmdSN: "
134		    "was %d, is %d", conn->conn_cmdsn,
135		    ntohl(bhslr->bhslr_cmdsn));
136	}
137	if (initial == false &&
138	    ntohl(bhslr->bhslr_expstatsn) != conn->conn_statsn) {
139		login_send_error(request, 0x02, 0x05);
140		log_errx(1, "received Login PDU with wrong ExpStatSN: "
141		    "is %d, should be %d", ntohl(bhslr->bhslr_expstatsn),
142		    conn->conn_statsn);
143	}
144	conn->conn_cmdsn = ntohl(bhslr->bhslr_cmdsn);
145
146	return (request);
147}
148
149static struct pdu *
150login_new_response(struct pdu *request)
151{
152	struct pdu *response;
153	struct connection *conn;
154	struct iscsi_bhs_login_request *bhslr;
155	struct iscsi_bhs_login_response *bhslr2;
156
157	bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
158	conn = request->pdu_connection;
159
160	response = pdu_new_response(request);
161	bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
162	bhslr2->bhslr_opcode = ISCSI_BHS_OPCODE_LOGIN_RESPONSE;
163	login_set_csg(response, BHSLR_STAGE_SECURITY_NEGOTIATION);
164	memcpy(bhslr2->bhslr_isid,
165	    bhslr->bhslr_isid, sizeof(bhslr2->bhslr_isid));
166	bhslr2->bhslr_initiator_task_tag = bhslr->bhslr_initiator_task_tag;
167	bhslr2->bhslr_statsn = htonl(conn->conn_statsn++);
168	bhslr2->bhslr_expcmdsn = htonl(conn->conn_cmdsn);
169	bhslr2->bhslr_maxcmdsn = htonl(conn->conn_cmdsn);
170
171	return (response);
172}
173
174static void
175login_send_error(struct pdu *request, char class, char detail)
176{
177	struct pdu *response;
178	struct iscsi_bhs_login_response *bhslr2;
179
180	log_debugx("sending Login Response PDU with failure class 0x%x/0x%x; "
181	    "see next line for reason", class, detail);
182	response = login_new_response(request);
183	bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
184	bhslr2->bhslr_status_class = class;
185	bhslr2->bhslr_status_detail = detail;
186
187	pdu_send(response);
188	pdu_delete(response);
189}
190
191static int
192login_list_contains(const char *list, const char *what)
193{
194	char *tofree, *str, *token;
195
196	tofree = str = checked_strdup(list);
197
198	while ((token = strsep(&str, ",")) != NULL) {
199		if (strcmp(token, what) == 0) {
200			free(tofree);
201			return (1);
202		}
203	}
204	free(tofree);
205	return (0);
206}
207
208static int
209login_list_prefers(const char *list,
210    const char *choice1, const char *choice2)
211{
212	char *tofree, *str, *token;
213
214	tofree = str = checked_strdup(list);
215
216	while ((token = strsep(&str, ",")) != NULL) {
217		if (strcmp(token, choice1) == 0) {
218			free(tofree);
219			return (1);
220		}
221		if (strcmp(token, choice2) == 0) {
222			free(tofree);
223			return (2);
224		}
225	}
226	free(tofree);
227	return (-1);
228}
229
230static int
231login_hex2int(const char hex)
232{
233	switch (hex) {
234	case '0':
235		return (0x00);
236	case '1':
237		return (0x01);
238	case '2':
239		return (0x02);
240	case '3':
241		return (0x03);
242	case '4':
243		return (0x04);
244	case '5':
245		return (0x05);
246	case '6':
247		return (0x06);
248	case '7':
249		return (0x07);
250	case '8':
251		return (0x08);
252	case '9':
253		return (0x09);
254	case 'a':
255	case 'A':
256		return (0x0a);
257	case 'b':
258	case 'B':
259		return (0x0b);
260	case 'c':
261	case 'C':
262		return (0x0c);
263	case 'd':
264	case 'D':
265		return (0x0d);
266	case 'e':
267	case 'E':
268		return (0x0e);
269	case 'f':
270	case 'F':
271		return (0x0f);
272	default:
273		return (-1);
274	}
275}
276
277/*
278 * XXX: Review this _carefully_.
279 */
280static int
281login_hex2bin(const char *hex, char **binp, size_t *bin_lenp)
282{
283	int i, hex_len, nibble;
284	bool lo = true; /* As opposed to 'hi'. */
285	char *bin;
286	size_t bin_off, bin_len;
287
288	if (strncasecmp(hex, "0x", strlen("0x")) != 0) {
289		log_warnx("malformed variable, should start with \"0x\"");
290		return (-1);
291	}
292
293	hex += strlen("0x");
294	hex_len = strlen(hex);
295	if (hex_len < 1) {
296		log_warnx("malformed variable; doesn't contain anything "
297		    "but \"0x\"");
298		return (-1);
299	}
300
301	bin_len = hex_len / 2 + hex_len % 2;
302	bin = calloc(bin_len, 1);
303	if (bin == NULL)
304		log_err(1, "calloc");
305
306	bin_off = bin_len - 1;
307	for (i = hex_len - 1; i >= 0; i--) {
308		nibble = login_hex2int(hex[i]);
309		if (nibble < 0) {
310			log_warnx("malformed variable, invalid char \"%c\"",
311			    hex[i]);
312			return (-1);
313		}
314
315		assert(bin_off < bin_len);
316		if (lo) {
317			bin[bin_off] = nibble;
318			lo = false;
319		} else {
320			bin[bin_off] |= nibble << 4;
321			bin_off--;
322			lo = true;
323		}
324	}
325
326	*binp = bin;
327	*bin_lenp = bin_len;
328	return (0);
329}
330
331static char *
332login_bin2hex(const char *bin, size_t bin_len)
333{
334	unsigned char *hex, *tmp, ch;
335	size_t hex_len;
336	size_t i;
337
338	hex_len = bin_len * 2 + 3; /* +2 for "0x", +1 for '\0'. */
339	hex = malloc(hex_len);
340	if (hex == NULL)
341		log_err(1, "malloc");
342
343	tmp = hex;
344	tmp += sprintf(tmp, "0x");
345	for (i = 0; i < bin_len; i++) {
346		ch = bin[i];
347		tmp += sprintf(tmp, "%02x", ch);
348	}
349
350	return (hex);
351}
352
353static void
354login_compute_md5(const char id, const char *secret,
355    const void *challenge, size_t challenge_len, void *response,
356    size_t response_len)
357{
358	MD5_CTX ctx;
359	int rv;
360
361	assert(response_len == MD5_DIGEST_LENGTH);
362
363	MD5_Init(&ctx);
364	MD5_Update(&ctx, &id, sizeof(id));
365	MD5_Update(&ctx, secret, strlen(secret));
366	MD5_Update(&ctx, challenge, challenge_len);
367	rv = MD5_Final(response, &ctx);
368	if (rv != 1)
369		log_errx(1, "MD5_Final");
370}
371
372#define	LOGIN_CHALLENGE_LEN	1024
373
374static struct pdu *
375login_receive_chap_a(struct connection *conn)
376{
377	struct pdu *request;
378	struct keys *request_keys;
379	const char *chap_a;
380
381	request = login_receive(conn, false);
382	request_keys = keys_new();
383	keys_load(request_keys, request);
384
385	chap_a = keys_find(request_keys, "CHAP_A");
386	if (chap_a == NULL) {
387		login_send_error(request, 0x02, 0x07);
388		log_errx(1, "received CHAP Login PDU without CHAP_A");
389	}
390	if (login_list_contains(chap_a, "5") == 0) {
391		login_send_error(request, 0x02, 0x01);
392		log_errx(1, "received CHAP Login PDU with unsupported CHAP_A "
393		    "\"%s\"", chap_a);
394	}
395	keys_delete(request_keys);
396
397	return (request);
398}
399
400static void
401login_send_chap_c(struct pdu *request, const unsigned char id,
402    const void *challenge, const size_t challenge_len)
403{
404	struct pdu *response;
405	struct keys *response_keys;
406	char *chap_c, chap_i[4];
407
408	chap_c = login_bin2hex(challenge, challenge_len);
409	snprintf(chap_i, sizeof(chap_i), "%d", id);
410
411	response = login_new_response(request);
412	response_keys = keys_new();
413	keys_add(response_keys, "CHAP_A", "5");
414	keys_add(response_keys, "CHAP_I", chap_i);
415	keys_add(response_keys, "CHAP_C", chap_c);
416	free(chap_c);
417	keys_save(response_keys, response);
418	pdu_send(response);
419	pdu_delete(response);
420	keys_delete(response_keys);
421}
422
423static struct pdu *
424login_receive_chap_r(struct connection *conn,
425    struct auth_group *ag, const unsigned char id, const void *challenge,
426    const size_t challenge_len, const struct auth **cap)
427{
428	struct pdu *request;
429	struct keys *request_keys;
430	const char *chap_n, *chap_r;
431	char *response_bin, expected_response_bin[MD5_DIGEST_LENGTH];
432	size_t response_bin_len;
433	const struct auth *auth;
434	int error;
435
436	request = login_receive(conn, false);
437	request_keys = keys_new();
438	keys_load(request_keys, request);
439
440	chap_n = keys_find(request_keys, "CHAP_N");
441	if (chap_n == NULL) {
442		login_send_error(request, 0x02, 0x07);
443		log_errx(1, "received CHAP Login PDU without CHAP_N");
444	}
445	chap_r = keys_find(request_keys, "CHAP_R");
446	if (chap_r == NULL) {
447		login_send_error(request, 0x02, 0x07);
448		log_errx(1, "received CHAP Login PDU without CHAP_R");
449	}
450	error = login_hex2bin(chap_r, &response_bin, &response_bin_len);
451	if (error != 0) {
452		login_send_error(request, 0x02, 0x07);
453		log_errx(1, "received CHAP Login PDU with malformed CHAP_R");
454	}
455
456	/*
457	 * Verify the response.
458	 */
459	assert(ag->ag_type == AG_TYPE_CHAP ||
460	    ag->ag_type == AG_TYPE_CHAP_MUTUAL);
461	auth = auth_find(ag, chap_n);
462	if (auth == NULL) {
463		login_send_error(request, 0x02, 0x01);
464		log_errx(1, "received CHAP Login with invalid user \"%s\"",
465		    chap_n);
466	}
467
468	assert(auth->a_secret != NULL);
469	assert(strlen(auth->a_secret) > 0);
470	login_compute_md5(id, auth->a_secret, challenge,
471	    challenge_len, expected_response_bin,
472	    sizeof(expected_response_bin));
473
474	if (memcmp(response_bin, expected_response_bin,
475	    sizeof(expected_response_bin)) != 0) {
476		login_send_error(request, 0x02, 0x01);
477		log_errx(1, "CHAP authentication failed for user \"%s\"",
478		    auth->a_user);
479	}
480
481	keys_delete(request_keys);
482	free(response_bin);
483
484	*cap = auth;
485	return (request);
486}
487
488static void
489login_send_chap_success(struct pdu *request,
490    const struct auth *auth)
491{
492	struct pdu *response;
493	struct keys *request_keys, *response_keys;
494	struct iscsi_bhs_login_response *bhslr2;
495	const char *chap_i, *chap_c;
496	char *chap_r, *challenge, response_bin[MD5_DIGEST_LENGTH];
497	size_t challenge_len;
498	unsigned char id;
499	int error;
500
501	response = login_new_response(request);
502	bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
503	bhslr2->bhslr_flags |= BHSLR_FLAGS_TRANSIT;
504	login_set_nsg(response, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
505
506	/*
507	 * Actually, one more thing: mutual authentication.
508	 */
509	request_keys = keys_new();
510	keys_load(request_keys, request);
511	chap_i = keys_find(request_keys, "CHAP_I");
512	chap_c = keys_find(request_keys, "CHAP_C");
513	if (chap_i != NULL || chap_c != NULL) {
514		if (chap_i == NULL) {
515			login_send_error(request, 0x02, 0x07);
516			log_errx(1, "initiator requested target "
517			    "authentication, but didn't send CHAP_I");
518		}
519		if (chap_c == NULL) {
520			login_send_error(request, 0x02, 0x07);
521			log_errx(1, "initiator requested target "
522			    "authentication, but didn't send CHAP_C");
523		}
524		if (auth->a_auth_group->ag_type != AG_TYPE_CHAP_MUTUAL) {
525			login_send_error(request, 0x02, 0x01);
526			log_errx(1, "initiator requests target authentication "
527			    "for user \"%s\", but mutual user/secret "
528			    "is not set", auth->a_user);
529		}
530
531		id = strtoul(chap_i, NULL, 10);
532		error = login_hex2bin(chap_c, &challenge, &challenge_len);
533		if (error != 0) {
534			login_send_error(request, 0x02, 0x07);
535			log_errx(1, "received CHAP Login PDU with malformed "
536			    "CHAP_C");
537		}
538
539		log_debugx("performing mutual authentication as user \"%s\"",
540		    auth->a_mutual_user);
541		login_compute_md5(id, auth->a_mutual_secret, challenge,
542		    challenge_len, response_bin, sizeof(response_bin));
543
544		chap_r = login_bin2hex(response_bin,
545		    sizeof(response_bin));
546		response_keys = keys_new();
547		keys_add(response_keys, "CHAP_N", auth->a_mutual_user);
548		keys_add(response_keys, "CHAP_R", chap_r);
549		free(chap_r);
550		keys_save(response_keys, response);
551		keys_delete(response_keys);
552	} else {
553		log_debugx("initiator did not request target authentication");
554	}
555
556	keys_delete(request_keys);
557	pdu_send(response);
558	pdu_delete(response);
559}
560
561static void
562login_chap(struct connection *conn, struct auth_group *ag)
563{
564	const struct auth *auth;
565	struct pdu *request;
566	char challenge_bin[LOGIN_CHALLENGE_LEN];
567	unsigned char id;
568	int rv;
569
570	/*
571	 * Receive CHAP_A PDU.
572	 */
573	log_debugx("beginning CHAP authentication; waiting for CHAP_A");
574	request = login_receive_chap_a(conn);
575
576	/*
577	 * Generate the challenge.
578	 */
579	rv = RAND_bytes(challenge_bin, sizeof(challenge_bin));
580	if (rv != 1) {
581		login_send_error(request, 0x03, 0x02);
582		log_errx(1, "RAND_bytes failed: %s",
583		    ERR_error_string(ERR_get_error(), NULL));
584	}
585	rv = RAND_bytes(&id, sizeof(id));
586	if (rv != 1) {
587		login_send_error(request, 0x03, 0x02);
588		log_errx(1, "RAND_bytes failed: %s",
589		    ERR_error_string(ERR_get_error(), NULL));
590	}
591
592	/*
593	 * Send the challenge.
594	 */
595	log_debugx("sending CHAP_C, binary challenge size is %zd bytes",
596	    sizeof(challenge_bin));
597	login_send_chap_c(request, id, challenge_bin,
598	    sizeof(challenge_bin));
599	pdu_delete(request);
600
601	/*
602	 * Receive CHAP_N/CHAP_R PDU and authenticate.
603	 */
604	log_debugx("waiting for CHAP_N/CHAP_R");
605	request = login_receive_chap_r(conn, ag, id, challenge_bin,
606	    sizeof(challenge_bin), &auth);
607
608	/*
609	 * Yay, authentication succeeded!
610	 */
611	log_debugx("authentication succeeded for user \"%s\"; "
612	    "transitioning to Negotiation Phase", auth->a_user);
613	login_send_chap_success(request, auth);
614	pdu_delete(request);
615}
616
617static void
618login_negotiate_key(struct pdu *request, const char *name,
619    const char *value, bool skipped_security, struct keys *response_keys)
620{
621	int which, tmp;
622	struct connection *conn;
623
624	conn = request->pdu_connection;
625
626	if (strcmp(name, "InitiatorName") == 0) {
627		if (!skipped_security)
628			log_errx(1, "initiator resent InitiatorName");
629	} else if (strcmp(name, "SessionType") == 0) {
630		if (!skipped_security)
631			log_errx(1, "initiator resent SessionType");
632	} else if (strcmp(name, "TargetName") == 0) {
633		if (!skipped_security)
634			log_errx(1, "initiator resent TargetName");
635	} else if (strcmp(name, "InitiatorAlias") == 0) {
636		if (conn->conn_initiator_alias != NULL)
637			free(conn->conn_initiator_alias);
638		conn->conn_initiator_alias = checked_strdup(value);
639	} else if (strcmp(value, "Irrelevant") == 0) {
640		/* Ignore. */
641	} else if (strcmp(name, "HeaderDigest") == 0) {
642		/*
643		 * We don't handle digests for discovery sessions.
644		 */
645		if (conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
646			log_debugx("discovery session; digests disabled");
647			keys_add(response_keys, name, "None");
648			return;
649		}
650
651		which = login_list_prefers(value, "CRC32C", "None");
652		switch (which) {
653		case 1:
654			log_debugx("initiator prefers CRC32C "
655			    "for header digest; we'll use it");
656			conn->conn_header_digest = CONN_DIGEST_CRC32C;
657			keys_add(response_keys, name, "CRC32C");
658			break;
659		case 2:
660			log_debugx("initiator prefers not to do "
661			    "header digest; we'll comply");
662			keys_add(response_keys, name, "None");
663			break;
664		default:
665			log_warnx("initiator sent unrecognized "
666			    "HeaderDigest value \"%s\"; will use None", value);
667			keys_add(response_keys, name, "None");
668			break;
669		}
670	} else if (strcmp(name, "DataDigest") == 0) {
671		if (conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
672			log_debugx("discovery session; digests disabled");
673			keys_add(response_keys, name, "None");
674			return;
675		}
676
677		which = login_list_prefers(value, "CRC32C", "None");
678		switch (which) {
679		case 1:
680			log_debugx("initiator prefers CRC32C "
681			    "for data digest; we'll use it");
682			conn->conn_data_digest = CONN_DIGEST_CRC32C;
683			keys_add(response_keys, name, "CRC32C");
684			break;
685		case 2:
686			log_debugx("initiator prefers not to do "
687			    "data digest; we'll comply");
688			keys_add(response_keys, name, "None");
689			break;
690		default:
691			log_warnx("initiator sent unrecognized "
692			    "DataDigest value \"%s\"; will use None", value);
693			keys_add(response_keys, name, "None");
694			break;
695		}
696	} else if (strcmp(name, "MaxConnections") == 0) {
697		keys_add(response_keys, name, "1");
698	} else if (strcmp(name, "InitialR2T") == 0) {
699		keys_add(response_keys, name, "Yes");
700	} else if (strcmp(name, "ImmediateData") == 0) {
701		if (conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
702			log_debugx("discovery session; ImmediateData irrelevant");
703			keys_add(response_keys, name, "Irrelevant");
704		} else {
705			if (strcmp(value, "Yes") == 0) {
706				conn->conn_immediate_data = true;
707				keys_add(response_keys, name, "Yes");
708			} else {
709				conn->conn_immediate_data = false;
710				keys_add(response_keys, name, "No");
711			}
712		}
713	} else if (strcmp(name, "MaxRecvDataSegmentLength") == 0) {
714		tmp = strtoul(value, NULL, 10);
715		if (tmp <= 0) {
716			login_send_error(request, 0x02, 0x00);
717			log_errx(1, "received invalid "
718			    "MaxRecvDataSegmentLength");
719		}
720		if (tmp > MAX_DATA_SEGMENT_LENGTH) {
721			log_debugx("capping MaxDataSegmentLength from %d to %d",
722			    tmp, MAX_DATA_SEGMENT_LENGTH);
723			tmp = MAX_DATA_SEGMENT_LENGTH;
724		}
725		conn->conn_max_data_segment_length = tmp;
726		keys_add_int(response_keys, name, tmp);
727	} else if (strcmp(name, "MaxBurstLength") == 0) {
728		tmp = strtoul(value, NULL, 10);
729		if (tmp <= 0) {
730			login_send_error(request, 0x02, 0x00);
731			log_errx(1, "received invalid MaxBurstLength");
732		}
733		if (tmp > MAX_BURST_LENGTH) {
734			log_debugx("capping MaxBurstLength from %d to %d",
735			    tmp, MAX_BURST_LENGTH);
736			tmp = MAX_BURST_LENGTH;
737		}
738		conn->conn_max_burst_length = tmp;
739		keys_add(response_keys, name, value);
740	} else if (strcmp(name, "FirstBurstLength") == 0) {
741		tmp = strtoul(value, NULL, 10);
742		if (tmp <= 0) {
743			login_send_error(request, 0x02, 0x00);
744			log_errx(1, "received invalid "
745			    "FirstBurstLength");
746		}
747		if (tmp > MAX_DATA_SEGMENT_LENGTH) {
748			log_debugx("capping FirstBurstLength from %d to %d",
749			    tmp, MAX_DATA_SEGMENT_LENGTH);
750			tmp = MAX_DATA_SEGMENT_LENGTH;
751		}
752		/*
753		 * We don't pass the value to the kernel; it only enforces
754		 * hardcoded limit anyway.
755		 */
756		keys_add_int(response_keys, name, tmp);
757	} else if (strcmp(name, "DefaultTime2Wait") == 0) {
758		keys_add(response_keys, name, value);
759	} else if (strcmp(name, "DefaultTime2Retain") == 0) {
760		keys_add(response_keys, name, "0");
761	} else if (strcmp(name, "MaxOutstandingR2T") == 0) {
762		keys_add(response_keys, name, "1");
763	} else if (strcmp(name, "DataPDUInOrder") == 0) {
764		keys_add(response_keys, name, "Yes");
765	} else if (strcmp(name, "DataSequenceInOrder") == 0) {
766		keys_add(response_keys, name, "Yes");
767	} else if (strcmp(name, "ErrorRecoveryLevel") == 0) {
768		keys_add(response_keys, name, "0");
769	} else if (strcmp(name, "OFMarker") == 0) {
770		keys_add(response_keys, name, "No");
771	} else if (strcmp(name, "IFMarker") == 0) {
772		keys_add(response_keys, name, "No");
773	} else {
774		log_debugx("unknown key \"%s\"; responding "
775		    "with NotUnderstood", name);
776		keys_add(response_keys, name, "NotUnderstood");
777	}
778}
779
780static void
781login_negotiate(struct connection *conn, struct pdu *request)
782{
783	struct pdu *response;
784	struct iscsi_bhs_login_response *bhslr2;
785	struct keys *request_keys, *response_keys;
786	int i;
787	bool skipped_security;
788
789	if (request == NULL) {
790		log_debugx("beginning operational parameter negotiation; "
791		    "waiting for Login PDU");
792		request = login_receive(conn, false);
793		skipped_security = false;
794	} else
795		skipped_security = true;
796
797	request_keys = keys_new();
798	keys_load(request_keys, request);
799
800	response = login_new_response(request);
801	bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
802	bhslr2->bhslr_flags |= BHSLR_FLAGS_TRANSIT;
803	bhslr2->bhslr_tsih = htons(0xbadd);
804	login_set_csg(response, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
805	login_set_nsg(response, BHSLR_STAGE_FULL_FEATURE_PHASE);
806	response_keys = keys_new();
807	for (i = 0; i < KEYS_MAX; i++) {
808		if (request_keys->keys_names[i] == NULL)
809			break;
810
811		login_negotiate_key(request, request_keys->keys_names[i],
812		    request_keys->keys_values[i], skipped_security,
813		    response_keys);
814	}
815
816	log_debugx("operational parameter negotiation done; "
817	    "transitioning to Full Feature Phase");
818
819	keys_save(response_keys, response);
820	pdu_send(response);
821	pdu_delete(response);
822	keys_delete(response_keys);
823	pdu_delete(request);
824	keys_delete(request_keys);
825}
826
827void
828login(struct connection *conn)
829{
830	struct pdu *request, *response;
831	struct iscsi_bhs_login_request *bhslr;
832	struct iscsi_bhs_login_response *bhslr2;
833	struct keys *request_keys, *response_keys;
834	struct auth_group *ag;
835	const char *initiator_name, *initiator_alias, *session_type,
836	    *target_name, *auth_method;
837	char *portal_group_tag;
838	int rv;
839
840	/*
841	 * Handle the initial Login Request - figure out required authentication
842	 * method and either transition to the next phase, if no authentication
843	 * is required, or call appropriate authentication code.
844	 */
845	log_debugx("beginning Login Phase; waiting for Login PDU");
846	request = login_receive(conn, true);
847	bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
848	if (bhslr->bhslr_tsih != 0) {
849		login_send_error(request, 0x02, 0x0a);
850		log_errx(1, "received Login PDU with non-zero TSIH");
851	}
852
853	memcpy(conn->conn_initiator_isid, bhslr->bhslr_isid,
854	    sizeof(conn->conn_initiator_isid));
855
856	/*
857	 * XXX: Implement the C flag some day.
858	 */
859	request_keys = keys_new();
860	keys_load(request_keys, request);
861
862	assert(conn->conn_initiator_name == NULL);
863	initiator_name = keys_find(request_keys, "InitiatorName");
864	if (initiator_name == NULL) {
865		login_send_error(request, 0x02, 0x07);
866		log_errx(1, "received Login PDU without InitiatorName");
867	}
868	if (valid_iscsi_name(initiator_name) == false) {
869		login_send_error(request, 0x02, 0x00);
870		log_errx(1, "received Login PDU with invalid InitiatorName");
871	}
872	conn->conn_initiator_name = checked_strdup(initiator_name);
873	log_set_peer_name(conn->conn_initiator_name);
874	/*
875	 * XXX: This doesn't work (does nothing) because of Capsicum.
876	 */
877	setproctitle("%s (%s)", conn->conn_initiator_addr, conn->conn_initiator_name);
878
879	initiator_alias = keys_find(request_keys, "InitiatorAlias");
880	if (initiator_alias != NULL)
881		conn->conn_initiator_alias = checked_strdup(initiator_alias);
882
883	assert(conn->conn_session_type == CONN_SESSION_TYPE_NONE);
884	session_type = keys_find(request_keys, "SessionType");
885	if (session_type != NULL) {
886		if (strcmp(session_type, "Normal") == 0) {
887			conn->conn_session_type = CONN_SESSION_TYPE_NORMAL;
888		} else if (strcmp(session_type, "Discovery") == 0) {
889			conn->conn_session_type = CONN_SESSION_TYPE_DISCOVERY;
890		} else {
891			login_send_error(request, 0x02, 0x00);
892			log_errx(1, "received Login PDU with invalid "
893			    "SessionType \"%s\"", session_type);
894		}
895	} else
896		conn->conn_session_type = CONN_SESSION_TYPE_NORMAL;
897
898	assert(conn->conn_target == NULL);
899	if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
900		target_name = keys_find(request_keys, "TargetName");
901		if (target_name == NULL) {
902			login_send_error(request, 0x02, 0x07);
903			log_errx(1, "received Login PDU without TargetName");
904		}
905
906		conn->conn_target =
907		    target_find(conn->conn_portal->p_portal_group->pg_conf,
908		    target_name);
909		if (conn->conn_target == NULL) {
910			login_send_error(request, 0x02, 0x03);
911			log_errx(1, "requested target \"%s\" not found",
912			    target_name);
913		}
914	}
915
916	/*
917	 * At this point we know what kind of authentication we need.
918	 */
919	if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
920		ag = conn->conn_target->t_auth_group;
921		if (ag->ag_name != NULL) {
922			log_debugx("initiator requests to connect "
923			    "to target \"%s\"; auth-group \"%s\"",
924			    conn->conn_target->t_name,
925			    conn->conn_target->t_auth_group->ag_name);
926		} else {
927			log_debugx("initiator requests to connect "
928			    "to target \"%s\"", conn->conn_target->t_name);
929		}
930	} else {
931		assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
932		ag = conn->conn_portal->p_portal_group->pg_discovery_auth_group;
933		if (ag->ag_name != NULL) {
934			log_debugx("initiator requests "
935			    "discovery session; auth-group \"%s\"", ag->ag_name);
936		} else {
937			log_debugx("initiator requests discovery session");
938		}
939	}
940
941	/*
942	 * Enforce initiator-name and initiator-portal.
943	 */
944	if (auth_name_defined(ag)) {
945		if (auth_name_find(ag, initiator_name) == NULL) {
946			login_send_error(request, 0x02, 0x02);
947			log_errx(1, "initiator does not match allowed "
948			    "initiator names");
949		}
950		log_debugx("initiator matches allowed initiator names");
951	} else {
952		log_debugx("auth-group does not define initiator name "
953		    "restrictions");
954	}
955
956	if (auth_portal_defined(ag)) {
957		if (auth_portal_find(ag, &conn->conn_initiator_sa) == NULL) {
958			login_send_error(request, 0x02, 0x02);
959			log_errx(1, "initiator does not match allowed "
960			    "initiator portals");
961		}
962		log_debugx("initiator matches allowed initiator portals");
963	} else {
964		log_debugx("auth-group does not define initiator portal "
965		    "restrictions");
966	}
967
968	/*
969	 * Let's see if the initiator intends to do any kind of authentication
970	 * at all.
971	 */
972	if (login_csg(request) == BHSLR_STAGE_OPERATIONAL_NEGOTIATION) {
973		if (ag->ag_type != AG_TYPE_NO_AUTHENTICATION) {
974			login_send_error(request, 0x02, 0x01);
975			log_errx(1, "initiator skipped the authentication, "
976			    "but authentication is required");
977		}
978
979		keys_delete(request_keys);
980
981		log_debugx("initiator skipped the authentication, "
982		    "and we don't need it; proceeding with negotiation");
983		login_negotiate(conn, request);
984		return;
985	}
986
987	if (ag->ag_type == AG_TYPE_NO_AUTHENTICATION) {
988		/*
989		 * Initiator might want to to authenticate,
990		 * but we don't need it.
991		 */
992		log_debugx("authentication not required; "
993		    "transitioning to operational parameter negotiation");
994
995		if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) == 0)
996			log_warnx("initiator did not set the \"T\" flag; "
997			    "transitioning anyway");
998
999		response = login_new_response(request);
1000		bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
1001		bhslr2->bhslr_flags |= BHSLR_FLAGS_TRANSIT;
1002		login_set_nsg(response,
1003		    BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
1004		response_keys = keys_new();
1005		/*
1006		 * Required by Linux initiator.
1007		 */
1008		auth_method = keys_find(request_keys, "AuthMethod");
1009		if (auth_method != NULL &&
1010		    login_list_contains(auth_method, "None"))
1011			keys_add(response_keys, "AuthMethod", "None");
1012
1013		if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
1014			if (conn->conn_target->t_alias != NULL)
1015				keys_add(response_keys,
1016				    "TargetAlias", conn->conn_target->t_alias);
1017			rv = asprintf(&portal_group_tag, "%d",
1018			    conn->conn_portal->p_portal_group->pg_tag);
1019			if (rv <= 0)
1020				log_err(1, "asprintf");
1021			keys_add(response_keys,
1022			    "TargetPortalGroupTag", portal_group_tag);
1023			free(portal_group_tag);
1024		}
1025		keys_save(response_keys, response);
1026		pdu_send(response);
1027		pdu_delete(response);
1028		keys_delete(response_keys);
1029		pdu_delete(request);
1030		keys_delete(request_keys);
1031
1032		login_negotiate(conn, NULL);
1033		return;
1034	}
1035
1036	if (ag->ag_type == AG_TYPE_DENY) {
1037		login_send_error(request, 0x02, 0x01);
1038		log_errx(1, "auth-type is \"deny\"");
1039	}
1040
1041	if (ag->ag_type == AG_TYPE_UNKNOWN) {
1042		/*
1043		 * This can happen with empty auth-group.
1044		 */
1045		login_send_error(request, 0x02, 0x01);
1046		log_errx(1, "auth-type not set, denying access");
1047	}
1048
1049	log_debugx("CHAP authentication required");
1050
1051	auth_method = keys_find(request_keys, "AuthMethod");
1052	if (auth_method == NULL) {
1053		login_send_error(request, 0x02, 0x07);
1054		log_errx(1, "received Login PDU without AuthMethod");
1055	}
1056	/*
1057	 * XXX: This should be Reject, not just a login failure (5.3.2).
1058	 */
1059	if (login_list_contains(auth_method, "CHAP") == 0) {
1060		login_send_error(request, 0x02, 0x01);
1061		log_errx(1, "initiator requests unsupported AuthMethod \"%s\" "
1062		    "instead of \"CHAP\"", auth_method);
1063	}
1064
1065	response = login_new_response(request);
1066
1067	response_keys = keys_new();
1068	keys_add(response_keys, "AuthMethod", "CHAP");
1069	if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
1070		rv = asprintf(&portal_group_tag, "%d",
1071		    conn->conn_portal->p_portal_group->pg_tag);
1072		if (rv <= 0)
1073			log_err(1, "asprintf");
1074		keys_add(response_keys,
1075		    "TargetPortalGroupTag", portal_group_tag);
1076		free(portal_group_tag);
1077		if (conn->conn_target->t_alias != NULL)
1078			keys_add(response_keys,
1079			    "TargetAlias", conn->conn_target->t_alias);
1080	}
1081	keys_save(response_keys, response);
1082
1083	pdu_send(response);
1084	pdu_delete(response);
1085	keys_delete(response_keys);
1086	pdu_delete(request);
1087	keys_delete(request_keys);
1088
1089	login_chap(conn, ag);
1090
1091	login_negotiate(conn, NULL);
1092}
1093