login.c revision 263733
1234949Sbapt/*-
2234949Sbapt * Copyright (c) 2012 The FreeBSD Foundation
3234949Sbapt * All rights reserved.
4234949Sbapt *
5234949Sbapt * This software was developed by Edward Tomasz Napierala under sponsorship
6234949Sbapt * from the FreeBSD Foundation.
7234949Sbapt *
8234949Sbapt * Redistribution and use in source and binary forms, with or without
9234949Sbapt * modification, are permitted provided that the following conditions
10234949Sbapt * are met:
11234949Sbapt * 1. Redistributions of source code must retain the above copyright
12234949Sbapt *    notice, this list of conditions and the following disclaimer.
13234949Sbapt * 2. Redistributions in binary form must reproduce the above copyright
14234949Sbapt *    notice, this list of conditions and the following disclaimer in the
15234949Sbapt *    documentation and/or other materials provided with the distribution.
16234949Sbapt *
17234949Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18234949Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19234949Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20234949Sbapt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21234949Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22234949Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23234949Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24234949Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25234949Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26234949Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27234949Sbapt * SUCH DAMAGE.
28234949Sbapt *
29234949Sbapt * $FreeBSD: stable/10/usr.sbin/ctld/login.c 263733 2014-03-25 12:33:16Z trasz $
30234949Sbapt */
31234949Sbapt
32234949Sbapt#include <assert.h>
33234949Sbapt#include <stdbool.h>
34234949Sbapt#include <stdint.h>
35234949Sbapt#include <stdio.h>
36234949Sbapt#include <stdlib.h>
37234949Sbapt#include <string.h>
38234949Sbapt#include <unistd.h>
39234949Sbapt#include <netinet/in.h>
40234949Sbapt#include <openssl/err.h>
41234949Sbapt#include <openssl/md5.h>
42234949Sbapt#include <openssl/rand.h>
43234949Sbapt
44234949Sbapt#include "ctld.h"
45234949Sbapt#include "iscsi_proto.h"
46234949Sbapt
47234949Sbaptstatic void login_send_error(struct pdu *request,
48234949Sbapt    char class, char detail);
49234949Sbapt
50234949Sbaptstatic void
51234949Sbaptlogin_set_nsg(struct pdu *response, int nsg)
52234949Sbapt{
53234949Sbapt	struct iscsi_bhs_login_response *bhslr;
54234949Sbapt
55234949Sbapt	assert(nsg == BHSLR_STAGE_SECURITY_NEGOTIATION ||
56234949Sbapt	    nsg == BHSLR_STAGE_OPERATIONAL_NEGOTIATION ||
57234949Sbapt	    nsg == BHSLR_STAGE_FULL_FEATURE_PHASE);
58234949Sbapt
59234949Sbapt	bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs;
60234949Sbapt
61234949Sbapt	bhslr->bhslr_flags &= 0xFC;
62234949Sbapt	bhslr->bhslr_flags |= nsg;
63234949Sbapt}
64234949Sbapt
65234949Sbaptstatic int
66234949Sbaptlogin_csg(const struct pdu *request)
67234949Sbapt{
68234949Sbapt	struct iscsi_bhs_login_request *bhslr;
69234949Sbapt
70234949Sbapt	bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
71234949Sbapt
72234949Sbapt	return ((bhslr->bhslr_flags & 0x0C) >> 2);
73234949Sbapt}
74234949Sbapt
75234949Sbaptstatic void
76234949Sbaptlogin_set_csg(struct pdu *response, int csg)
77234949Sbapt{
78234949Sbapt	struct iscsi_bhs_login_response *bhslr;
79234949Sbapt
80234949Sbapt	assert(csg == BHSLR_STAGE_SECURITY_NEGOTIATION ||
81234949Sbapt	    csg == BHSLR_STAGE_OPERATIONAL_NEGOTIATION ||
82234949Sbapt	    csg == BHSLR_STAGE_FULL_FEATURE_PHASE);
83234949Sbapt
84234949Sbapt	bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs;
85234949Sbapt
86234949Sbapt	bhslr->bhslr_flags &= 0xF3;
87234949Sbapt	bhslr->bhslr_flags |= csg << 2;
88234949Sbapt}
89234949Sbapt
90234949Sbaptstatic struct pdu *
91234949Sbaptlogin_receive(struct connection *conn, bool initial)
92234949Sbapt{
93234949Sbapt	struct pdu *request;
94234949Sbapt	struct iscsi_bhs_login_request *bhslr;
95234949Sbapt
96234949Sbapt	request = pdu_new(conn);
97234949Sbapt	pdu_receive(request);
98234949Sbapt	if ((request->pdu_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) !=
99234949Sbapt	    ISCSI_BHS_OPCODE_LOGIN_REQUEST) {
100234949Sbapt		/*
101234949Sbapt		 * The first PDU in session is special - if we receive any PDU
102234949Sbapt		 * different than login request, we have to drop the connection
103234949Sbapt		 * without sending response ("A target receiving any PDU
104234949Sbapt		 * except a Login request before the Login Phase is started MUST
105234949Sbapt		 * immediately terminate the connection on which the PDU
106234949Sbapt		 * was received.")
107234949Sbapt		 */
108234949Sbapt		if (initial == false)
109234949Sbapt			login_send_error(request, 0x02, 0x0b);
110234949Sbapt		log_errx(1, "protocol error: received invalid opcode 0x%x",
111234949Sbapt		    request->pdu_bhs->bhs_opcode);
112234949Sbapt	}
113234949Sbapt	bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
114234949Sbapt	/*
115234949Sbapt	 * XXX: Implement the C flag some day.
116234949Sbapt	 */
117234949Sbapt	if ((bhslr->bhslr_flags & BHSLR_FLAGS_CONTINUE) != 0) {
118234949Sbapt		login_send_error(request, 0x03, 0x00);
119234949Sbapt		log_errx(1, "received Login PDU with unsupported \"C\" flag");
120234949Sbapt	}
121234949Sbapt	if (bhslr->bhslr_version_max != 0x00) {
122234949Sbapt		login_send_error(request, 0x02, 0x05);
123234949Sbapt		log_errx(1, "received Login PDU with unsupported "
124234949Sbapt		    "Version-max 0x%x", bhslr->bhslr_version_max);
125234949Sbapt	}
126234949Sbapt	if (bhslr->bhslr_version_min != 0x00) {
127234949Sbapt		login_send_error(request, 0x02, 0x05);
128234949Sbapt		log_errx(1, "received Login PDU with unsupported "
129234949Sbapt		    "Version-min 0x%x", bhslr->bhslr_version_min);
130234949Sbapt	}
131234949Sbapt	if (ntohl(bhslr->bhslr_cmdsn) < conn->conn_cmdsn) {
132234949Sbapt		login_send_error(request, 0x02, 0x05);
133234949Sbapt		log_errx(1, "received Login PDU with decreasing CmdSN: "
134234949Sbapt		    "was %d, is %d", conn->conn_cmdsn,
135234949Sbapt		    ntohl(bhslr->bhslr_cmdsn));
136234949Sbapt	}
137234949Sbapt	if (initial == false &&
138234949Sbapt	    ntohl(bhslr->bhslr_expstatsn) != conn->conn_statsn) {
139234949Sbapt		login_send_error(request, 0x02, 0x05);
140234949Sbapt		log_errx(1, "received Login PDU with wrong ExpStatSN: "
141234949Sbapt		    "is %d, should be %d", ntohl(bhslr->bhslr_expstatsn),
142234949Sbapt		    conn->conn_statsn);
143234949Sbapt	}
144234949Sbapt	conn->conn_cmdsn = ntohl(bhslr->bhslr_cmdsn);
145234949Sbapt
146234949Sbapt	return (request);
147234949Sbapt}
148234949Sbapt
149234949Sbaptstatic struct pdu *
150234949Sbaptlogin_new_response(struct pdu *request)
151234949Sbapt{
152234949Sbapt	struct pdu *response;
153234949Sbapt	struct connection *conn;
154234949Sbapt	struct iscsi_bhs_login_request *bhslr;
155234949Sbapt	struct iscsi_bhs_login_response *bhslr2;
156234949Sbapt
157234949Sbapt	bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
158234949Sbapt	conn = request->pdu_connection;
159234949Sbapt
160234949Sbapt	response = pdu_new_response(request);
161234949Sbapt	bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
162234949Sbapt	bhslr2->bhslr_opcode = ISCSI_BHS_OPCODE_LOGIN_RESPONSE;
163234949Sbapt	login_set_csg(response, BHSLR_STAGE_SECURITY_NEGOTIATION);
164234949Sbapt	memcpy(bhslr2->bhslr_isid,
165234949Sbapt	    bhslr->bhslr_isid, sizeof(bhslr2->bhslr_isid));
166234949Sbapt	bhslr2->bhslr_initiator_task_tag = bhslr->bhslr_initiator_task_tag;
167234949Sbapt	bhslr2->bhslr_statsn = htonl(conn->conn_statsn++);
168234949Sbapt	bhslr2->bhslr_expcmdsn = htonl(conn->conn_cmdsn);
169234949Sbapt	bhslr2->bhslr_maxcmdsn = htonl(conn->conn_cmdsn);
170234949Sbapt
171234949Sbapt	return (response);
172234949Sbapt}
173234949Sbapt
174234949Sbaptstatic void
175234949Sbaptlogin_send_error(struct pdu *request, char class, char detail)
176234949Sbapt{
177234949Sbapt	struct pdu *response;
178234949Sbapt	struct iscsi_bhs_login_response *bhslr2;
179234949Sbapt
180234949Sbapt	log_debugx("sending Login Response PDU with failure class 0x%x/0x%x; "
181234949Sbapt	    "see next line for reason", class, detail);
182234949Sbapt	response = login_new_response(request);
183234949Sbapt	bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
184234949Sbapt	bhslr2->bhslr_status_class = class;
185234949Sbapt	bhslr2->bhslr_status_detail = detail;
186234949Sbapt
187234949Sbapt	pdu_send(response);
188234949Sbapt	pdu_delete(response);
189234949Sbapt}
190234949Sbapt
191234949Sbaptstatic int
192234949Sbaptlogin_list_contains(const char *list, const char *what)
193234949Sbapt{
194234949Sbapt	char *tofree, *str, *token;
195234949Sbapt
196234949Sbapt	tofree = str = checked_strdup(list);
197234949Sbapt
198234949Sbapt	while ((token = strsep(&str, ",")) != NULL) {
199234949Sbapt		if (strcmp(token, what) == 0) {
200234949Sbapt			free(tofree);
201234949Sbapt			return (1);
202234949Sbapt		}
203234949Sbapt	}
204234949Sbapt	free(tofree);
205234949Sbapt	return (0);
206234949Sbapt}
207234949Sbapt
208234949Sbaptstatic int
209234949Sbaptlogin_list_prefers(const char *list,
210234949Sbapt    const char *choice1, const char *choice2)
211234949Sbapt{
212234949Sbapt	char *tofree, *str, *token;
213234949Sbapt
214234949Sbapt	tofree = str = checked_strdup(list);
215234949Sbapt
216234949Sbapt	while ((token = strsep(&str, ",")) != NULL) {
217234949Sbapt		if (strcmp(token, choice1) == 0) {
218234949Sbapt			free(tofree);
219234949Sbapt			return (1);
220234949Sbapt		}
221234949Sbapt		if (strcmp(token, choice2) == 0) {
222234949Sbapt			free(tofree);
223234949Sbapt			return (2);
224234949Sbapt		}
225234949Sbapt	}
226234949Sbapt	free(tofree);
227234949Sbapt	return (-1);
228234949Sbapt}
229234949Sbapt
230234949Sbaptstatic int
231234949Sbaptlogin_hex2int(const char hex)
232234949Sbapt{
233234949Sbapt	switch (hex) {
234234949Sbapt	case '0':
235234949Sbapt		return (0x00);
236234949Sbapt	case '1':
237234949Sbapt		return (0x01);
238234949Sbapt	case '2':
239234949Sbapt		return (0x02);
240234949Sbapt	case '3':
241234949Sbapt		return (0x03);
242234949Sbapt	case '4':
243234949Sbapt		return (0x04);
244234949Sbapt	case '5':
245234949Sbapt		return (0x05);
246234949Sbapt	case '6':
247234949Sbapt		return (0x06);
248234949Sbapt	case '7':
249234949Sbapt		return (0x07);
250234949Sbapt	case '8':
251234949Sbapt		return (0x08);
252234949Sbapt	case '9':
253234949Sbapt		return (0x09);
254234949Sbapt	case 'a':
255234949Sbapt	case 'A':
256234949Sbapt		return (0x0a);
257234949Sbapt	case 'b':
258234949Sbapt	case 'B':
259234949Sbapt		return (0x0b);
260234949Sbapt	case 'c':
261234949Sbapt	case 'C':
262234949Sbapt		return (0x0c);
263234949Sbapt	case 'd':
264234949Sbapt	case 'D':
265234949Sbapt		return (0x0d);
266234949Sbapt	case 'e':
267234949Sbapt	case 'E':
268234949Sbapt		return (0x0e);
269234949Sbapt	case 'f':
270234949Sbapt	case 'F':
271234949Sbapt		return (0x0f);
272234949Sbapt	default:
273234949Sbapt		return (-1);
274234949Sbapt	}
275234949Sbapt}
276234949Sbapt
277251143Sbapt/*
278234949Sbapt * XXX: Review this _carefully_.
279234949Sbapt */
280234949Sbaptstatic int
281234949Sbaptlogin_hex2bin(const char *hex, char **binp, size_t *bin_lenp)
282234949Sbapt{
283234949Sbapt	int i, hex_len, nibble;
284234949Sbapt	bool lo = true; /* As opposed to 'hi'. */
285234949Sbapt	char *bin;
286234949Sbapt	size_t bin_off, bin_len;
287234949Sbapt
288234949Sbapt	if (strncasecmp(hex, "0x", strlen("0x")) != 0) {
289234949Sbapt		log_warnx("malformed variable, should start with \"0x\"");
290234949Sbapt		return (-1);
291234949Sbapt	}
292234949Sbapt
293234949Sbapt	hex += strlen("0x");
294234949Sbapt	hex_len = strlen(hex);
295234949Sbapt	if (hex_len < 1) {
296234949Sbapt		log_warnx("malformed variable; doesn't contain anything "
297234949Sbapt		    "but \"0x\"");
298234949Sbapt		return (-1);
299234949Sbapt	}
300234949Sbapt
301234949Sbapt	bin_len = hex_len / 2 + hex_len % 2;
302234949Sbapt	bin = calloc(bin_len, 1);
303234949Sbapt	if (bin == NULL)
304234949Sbapt		log_err(1, "calloc");
305234949Sbapt
306234949Sbapt	bin_off = bin_len - 1;
307234949Sbapt	for (i = hex_len - 1; i >= 0; i--) {
308234949Sbapt		nibble = login_hex2int(hex[i]);
309234949Sbapt		if (nibble < 0) {
310234949Sbapt			log_warnx("malformed variable, invalid char \"%c\"",
311234949Sbapt			    hex[i]);
312234949Sbapt			return (-1);
313234949Sbapt		}
314234949Sbapt
315234949Sbapt		assert(bin_off < bin_len);
316234949Sbapt		if (lo) {
317234949Sbapt			bin[bin_off] = nibble;
318234949Sbapt			lo = false;
319234949Sbapt		} else {
320234949Sbapt			bin[bin_off] |= nibble << 4;
321234949Sbapt			bin_off--;
322234949Sbapt			lo = true;
323234949Sbapt		}
324234949Sbapt	}
325234949Sbapt
326234949Sbapt	*binp = bin;
327234949Sbapt	*bin_lenp = bin_len;
328234949Sbapt	return (0);
329234949Sbapt}
330234949Sbapt
331234949Sbaptstatic char *
332234949Sbaptlogin_bin2hex(const char *bin, size_t bin_len)
333234949Sbapt{
334234949Sbapt	unsigned char *hex, *tmp, ch;
335234949Sbapt	size_t hex_len;
336234949Sbapt	size_t i;
337234949Sbapt
338234949Sbapt	hex_len = bin_len * 2 + 3; /* +2 for "0x", +1 for '\0'. */
339234949Sbapt	hex = malloc(hex_len);
340234949Sbapt	if (hex == NULL)
341234949Sbapt		log_err(1, "malloc");
342234949Sbapt
343234949Sbapt	tmp = hex;
344234949Sbapt	tmp += sprintf(tmp, "0x");
345234949Sbapt	for (i = 0; i < bin_len; i++) {
346234949Sbapt		ch = bin[i];
347234949Sbapt		tmp += sprintf(tmp, "%02x", ch);
348234949Sbapt	}
349234949Sbapt
350234949Sbapt	return (hex);
351234949Sbapt}
352234949Sbapt
353234949Sbaptstatic void
354234949Sbaptlogin_compute_md5(const char id, const char *secret,
355234949Sbapt    const void *challenge, size_t challenge_len, void *response,
356234949Sbapt    size_t response_len)
357234949Sbapt{
358234949Sbapt	MD5_CTX ctx;
359234949Sbapt	int rv;
360234949Sbapt
361234949Sbapt	assert(response_len == MD5_DIGEST_LENGTH);
362234949Sbapt
363234949Sbapt	MD5_Init(&ctx);
364234949Sbapt	MD5_Update(&ctx, &id, sizeof(id));
365234949Sbapt	MD5_Update(&ctx, secret, strlen(secret));
366234949Sbapt	MD5_Update(&ctx, challenge, challenge_len);
367234949Sbapt	rv = MD5_Final(response, &ctx);
368234949Sbapt	if (rv != 1)
369234949Sbapt		log_errx(1, "MD5_Final");
370234949Sbapt}
371234949Sbapt
372234949Sbapt#define	LOGIN_CHALLENGE_LEN	1024
373234949Sbapt
374234949Sbaptstatic struct pdu *
375234949Sbaptlogin_receive_chap_a(struct connection *conn)
376234949Sbapt{
377234949Sbapt	struct pdu *request;
378234949Sbapt	struct keys *request_keys;
379234949Sbapt	const char *chap_a;
380234949Sbapt
381234949Sbapt	request = login_receive(conn, false);
382234949Sbapt	request_keys = keys_new();
383234949Sbapt	keys_load(request_keys, request);
384234949Sbapt
385234949Sbapt	chap_a = keys_find(request_keys, "CHAP_A");
386234949Sbapt	if (chap_a == NULL) {
387234949Sbapt		login_send_error(request, 0x02, 0x07);
388234949Sbapt		log_errx(1, "received CHAP Login PDU without CHAP_A");
389234949Sbapt	}
390234949Sbapt	if (login_list_contains(chap_a, "5") == 0) {
391234949Sbapt		login_send_error(request, 0x02, 0x01);
392234949Sbapt		log_errx(1, "received CHAP Login PDU with unsupported CHAP_A "
393234949Sbapt		    "\"%s\"", chap_a);
394234949Sbapt	}
395234949Sbapt	keys_delete(request_keys);
396234949Sbapt
397234949Sbapt	return (request);
398234949Sbapt}
399234949Sbapt
400234949Sbaptstatic void
401234949Sbaptlogin_send_chap_c(struct pdu *request, const unsigned char id,
402234949Sbapt    const void *challenge, const size_t challenge_len)
403234949Sbapt{
404234949Sbapt	struct pdu *response;
405234949Sbapt	struct keys *response_keys;
406234949Sbapt	char *chap_c, chap_i[4];
407234949Sbapt
408234949Sbapt	chap_c = login_bin2hex(challenge, challenge_len);
409234949Sbapt	snprintf(chap_i, sizeof(chap_i), "%d", id);
410234949Sbapt
411234949Sbapt	response = login_new_response(request);
412234949Sbapt	response_keys = keys_new();
413234949Sbapt	keys_add(response_keys, "CHAP_A", "5");
414234949Sbapt	keys_add(response_keys, "CHAP_I", chap_i);
415234949Sbapt	keys_add(response_keys, "CHAP_C", chap_c);
416234949Sbapt	free(chap_c);
417234949Sbapt	keys_save(response_keys, response);
418234949Sbapt	pdu_send(response);
419234949Sbapt	pdu_delete(response);
420234949Sbapt	keys_delete(response_keys);
421234949Sbapt}
422234949Sbapt
423234949Sbaptstatic struct pdu *
424234949Sbaptlogin_receive_chap_r(struct connection *conn,
425234949Sbapt    struct auth_group *ag, const unsigned char id, const void *challenge,
426234949Sbapt    const size_t challenge_len, const struct auth **cap)
427234949Sbapt{
428234949Sbapt	struct pdu *request;
429234949Sbapt	struct keys *request_keys;
430234949Sbapt	const char *chap_n, *chap_r;
431234949Sbapt	char *response_bin, expected_response_bin[MD5_DIGEST_LENGTH];
432234949Sbapt	size_t response_bin_len;
433234949Sbapt	const struct auth *auth;
434234949Sbapt	int error;
435234949Sbapt
436234949Sbapt	request = login_receive(conn, false);
437234949Sbapt	request_keys = keys_new();
438234949Sbapt	keys_load(request_keys, request);
439234949Sbapt
440234949Sbapt	chap_n = keys_find(request_keys, "CHAP_N");
441234949Sbapt	if (chap_n == NULL) {
442234949Sbapt		login_send_error(request, 0x02, 0x07);
443234949Sbapt		log_errx(1, "received CHAP Login PDU without CHAP_N");
444234949Sbapt	}
445234949Sbapt	chap_r = keys_find(request_keys, "CHAP_R");
446234949Sbapt	if (chap_r == NULL) {
447234949Sbapt		login_send_error(request, 0x02, 0x07);
448234949Sbapt		log_errx(1, "received CHAP Login PDU without CHAP_R");
449234949Sbapt	}
450234949Sbapt	error = login_hex2bin(chap_r, &response_bin, &response_bin_len);
451234949Sbapt	if (error != 0) {
452234949Sbapt		login_send_error(request, 0x02, 0x07);
453234949Sbapt		log_errx(1, "received CHAP Login PDU with malformed CHAP_R");
454234949Sbapt	}
455234949Sbapt
456234949Sbapt	/*
457234949Sbapt	 * Verify the response.
458234949Sbapt	 */
459234949Sbapt	assert(ag->ag_type == AG_TYPE_CHAP ||
460234949Sbapt	    ag->ag_type == AG_TYPE_CHAP_MUTUAL);
461234949Sbapt	auth = auth_find(ag, chap_n);
462234949Sbapt	if (auth == NULL) {
463234949Sbapt		login_send_error(request, 0x02, 0x01);
464234949Sbapt		log_errx(1, "received CHAP Login with invalid user \"%s\"",
465234949Sbapt		    chap_n);
466234949Sbapt	}
467234949Sbapt
468234949Sbapt	assert(auth->a_secret != NULL);
469234949Sbapt	assert(strlen(auth->a_secret) > 0);
470234949Sbapt	login_compute_md5(id, auth->a_secret, challenge,
471234949Sbapt	    challenge_len, expected_response_bin,
472234949Sbapt	    sizeof(expected_response_bin));
473234949Sbapt
474234949Sbapt	if (memcmp(response_bin, expected_response_bin,
475234949Sbapt	    sizeof(expected_response_bin)) != 0) {
476234949Sbapt		login_send_error(request, 0x02, 0x01);
477234949Sbapt		log_errx(1, "CHAP authentication failed for user \"%s\"",
478234949Sbapt		    auth->a_user);
479234949Sbapt	}
480234949Sbapt
481234949Sbapt	keys_delete(request_keys);
482234949Sbapt	free(response_bin);
483234949Sbapt
484234949Sbapt	*cap = auth;
485234949Sbapt	return (request);
486234949Sbapt}
487234949Sbapt
488234949Sbaptstatic void
489234949Sbaptlogin_send_chap_success(struct pdu *request,
490234949Sbapt    const struct auth *auth)
491234949Sbapt{
492234949Sbapt	struct pdu *response;
493234949Sbapt	struct keys *request_keys, *response_keys;
494234949Sbapt	struct iscsi_bhs_login_response *bhslr2;
495234949Sbapt	const char *chap_i, *chap_c;
496234949Sbapt	char *chap_r, *challenge, response_bin[MD5_DIGEST_LENGTH];
497234949Sbapt	size_t challenge_len;
498234949Sbapt	unsigned char id;
499234949Sbapt	int error;
500234949Sbapt
501234949Sbapt	response = login_new_response(request);
502234949Sbapt	bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
503234949Sbapt	bhslr2->bhslr_flags |= BHSLR_FLAGS_TRANSIT;
504234949Sbapt	login_set_nsg(response, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
505234949Sbapt
506234949Sbapt	/*
507234949Sbapt	 * Actually, one more thing: mutual authentication.
508234949Sbapt	 */
509234949Sbapt	request_keys = keys_new();
510234949Sbapt	keys_load(request_keys, request);
511234949Sbapt	chap_i = keys_find(request_keys, "CHAP_I");
512234949Sbapt	chap_c = keys_find(request_keys, "CHAP_C");
513234949Sbapt	if (chap_i != NULL || chap_c != NULL) {
514234949Sbapt		if (chap_i == NULL) {
515234949Sbapt			login_send_error(request, 0x02, 0x07);
516234949Sbapt			log_errx(1, "initiator requested target "
517234949Sbapt			    "authentication, but didn't send CHAP_I");
518234949Sbapt		}
519234949Sbapt		if (chap_c == NULL) {
520234949Sbapt			login_send_error(request, 0x02, 0x07);
521234949Sbapt			log_errx(1, "initiator requested target "
522234949Sbapt			    "authentication, but didn't send CHAP_C");
523234949Sbapt		}
524234949Sbapt		if (auth->a_auth_group->ag_type != AG_TYPE_CHAP_MUTUAL) {
525234949Sbapt			login_send_error(request, 0x02, 0x01);
526234949Sbapt			log_errx(1, "initiator requests target authentication "
527234949Sbapt			    "for user \"%s\", but mutual user/secret "
528234949Sbapt			    "is not set", auth->a_user);
529234949Sbapt		}
530234949Sbapt
531234949Sbapt		id = strtoul(chap_i, NULL, 10);
532234949Sbapt		error = login_hex2bin(chap_c, &challenge, &challenge_len);
533234949Sbapt		if (error != 0) {
534234949Sbapt			login_send_error(request, 0x02, 0x07);
535234949Sbapt			log_errx(1, "received CHAP Login PDU with malformed "
536234949Sbapt			    "CHAP_C");
537234949Sbapt		}
538234949Sbapt
539234949Sbapt		log_debugx("performing mutual authentication as user \"%s\"",
540234949Sbapt		    auth->a_mutual_user);
541234949Sbapt		login_compute_md5(id, auth->a_mutual_secret, challenge,
542234949Sbapt		    challenge_len, response_bin, sizeof(response_bin));
543234949Sbapt
544234949Sbapt		chap_r = login_bin2hex(response_bin,
545234949Sbapt		    sizeof(response_bin));
546234949Sbapt		response_keys = keys_new();
547234949Sbapt		keys_add(response_keys, "CHAP_N", auth->a_mutual_user);
548234949Sbapt		keys_add(response_keys, "CHAP_R", chap_r);
549234949Sbapt		free(chap_r);
550234949Sbapt		keys_save(response_keys, response);
551234949Sbapt		keys_delete(response_keys);
552234949Sbapt	} else {
553234949Sbapt		log_debugx("initiator did not request target authentication");
554234949Sbapt	}
555234949Sbapt
556234949Sbapt	keys_delete(request_keys);
557234949Sbapt	pdu_send(response);
558234949Sbapt	pdu_delete(response);
559234949Sbapt}
560234949Sbapt
561234949Sbaptstatic void
562234949Sbaptlogin_chap(struct connection *conn, struct auth_group *ag)
563234949Sbapt{
564234949Sbapt	const struct auth *auth;
565234949Sbapt	struct pdu *request;
566234949Sbapt	char challenge_bin[LOGIN_CHALLENGE_LEN];
567234949Sbapt	unsigned char id;
568234949Sbapt	int rv;
569234949Sbapt
570234949Sbapt	/*
571234949Sbapt	 * Receive CHAP_A PDU.
572234949Sbapt	 */
573234949Sbapt	log_debugx("beginning CHAP authentication; waiting for CHAP_A");
574234949Sbapt	request = login_receive_chap_a(conn);
575234949Sbapt
576234949Sbapt	/*
577234949Sbapt	 * Generate the challenge.
578234949Sbapt	 */
579234949Sbapt	rv = RAND_bytes(challenge_bin, sizeof(challenge_bin));
580234949Sbapt	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 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("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	/*
854	 * XXX: Implement the C flag some day.
855	 */
856	request_keys = keys_new();
857	keys_load(request_keys, request);
858
859	assert(conn->conn_initiator_name == NULL);
860	initiator_name = keys_find(request_keys, "InitiatorName");
861	if (initiator_name == NULL) {
862		login_send_error(request, 0x02, 0x07);
863		log_errx(1, "received Login PDU without InitiatorName");
864	}
865	if (valid_iscsi_name(initiator_name) == false) {
866		login_send_error(request, 0x02, 0x00);
867		log_errx(1, "received Login PDU with invalid InitiatorName");
868	}
869	conn->conn_initiator_name = checked_strdup(initiator_name);
870	log_set_peer_name(conn->conn_initiator_name);
871	/*
872	 * XXX: This doesn't work (does nothing) because of Capsicum.
873	 */
874	setproctitle("%s (%s)", conn->conn_initiator_addr, conn->conn_initiator_name);
875
876	initiator_alias = keys_find(request_keys, "InitiatorAlias");
877	if (initiator_alias != NULL)
878		conn->conn_initiator_alias = checked_strdup(initiator_alias);
879
880	assert(conn->conn_session_type == CONN_SESSION_TYPE_NONE);
881	session_type = keys_find(request_keys, "SessionType");
882	if (session_type != NULL) {
883		if (strcmp(session_type, "Normal") == 0) {
884			conn->conn_session_type = CONN_SESSION_TYPE_NORMAL;
885		} else if (strcmp(session_type, "Discovery") == 0) {
886			conn->conn_session_type = CONN_SESSION_TYPE_DISCOVERY;
887		} else {
888			login_send_error(request, 0x02, 0x00);
889			log_errx(1, "received Login PDU with invalid "
890			    "SessionType \"%s\"", session_type);
891		}
892	} else
893		conn->conn_session_type = CONN_SESSION_TYPE_NORMAL;
894
895	assert(conn->conn_target == NULL);
896	if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
897		target_name = keys_find(request_keys, "TargetName");
898		if (target_name == NULL) {
899			login_send_error(request, 0x02, 0x07);
900			log_errx(1, "received Login PDU without TargetName");
901		}
902
903		conn->conn_target =
904		    target_find(conn->conn_portal->p_portal_group->pg_conf,
905		    target_name);
906		if (conn->conn_target == NULL) {
907			login_send_error(request, 0x02, 0x03);
908			log_errx(1, "requested target \"%s\" not found",
909			    target_name);
910		}
911	}
912
913	/*
914	 * At this point we know what kind of authentication we need.
915	 */
916	if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
917		ag = conn->conn_target->t_auth_group;
918		if (ag->ag_name != NULL) {
919			log_debugx("initiator requests to connect "
920			    "to target \"%s\"; auth-group \"%s\"",
921			    conn->conn_target->t_name,
922			    conn->conn_target->t_auth_group->ag_name);
923		} else {
924			log_debugx("initiator requests to connect "
925			    "to target \"%s\"", conn->conn_target->t_name);
926		}
927	} else {
928		assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
929		ag = conn->conn_portal->p_portal_group->pg_discovery_auth_group;
930		if (ag->ag_name != NULL) {
931			log_debugx("initiator requests "
932			    "discovery session; auth-group \"%s\"", ag->ag_name);
933		} else {
934			log_debugx("initiator requests discovery session");
935		}
936	}
937
938	/*
939	 * Enforce initiator-name and initiator-portal.
940	 */
941	if (auth_name_defined(ag)) {
942		if (auth_name_find(ag, initiator_name) == NULL) {
943			login_send_error(request, 0x02, 0x02);
944			log_errx(1, "initiator does not match allowed "
945			    "initiator names");
946		}
947		log_debugx("initiator matches allowed initiator names");
948	} else {
949		log_debugx("auth-group does not define initiator name "
950		    "restrictions");
951	}
952
953	if (auth_portal_defined(ag)) {
954		if (auth_portal_find(ag, conn->conn_initiator_addr) == NULL) {
955			login_send_error(request, 0x02, 0x02);
956			log_errx(1, "initiator does not match allowed "
957			    "initiator portals");
958		}
959		log_debugx("initiator matches allowed initiator portals");
960	} else {
961		log_debugx("auth-group does not define initiator portal "
962		    "restrictions");
963	}
964
965	/*
966	 * Let's see if the initiator intends to do any kind of authentication
967	 * at all.
968	 */
969	if (login_csg(request) == BHSLR_STAGE_OPERATIONAL_NEGOTIATION) {
970		if (ag->ag_type != AG_TYPE_NO_AUTHENTICATION) {
971			login_send_error(request, 0x02, 0x01);
972			log_errx(1, "initiator skipped the authentication, "
973			    "but authentication is required");
974		}
975
976		keys_delete(request_keys);
977
978		log_debugx("initiator skipped the authentication, "
979		    "and we don't need it; proceeding with negotiation");
980		login_negotiate(conn, request);
981		return;
982	}
983
984	if (ag->ag_type == AG_TYPE_NO_AUTHENTICATION) {
985		/*
986		 * Initiator might want to to authenticate,
987		 * but we don't need it.
988		 */
989		log_debugx("authentication not required; "
990		    "transitioning to parameter negotiation");
991
992		if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) == 0)
993			log_warnx("initiator did not set the \"T\" flag; "
994			    "transitioning anyway");
995
996		response = login_new_response(request);
997		bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
998		bhslr2->bhslr_flags |= BHSLR_FLAGS_TRANSIT;
999		login_set_nsg(response,
1000		    BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
1001		response_keys = keys_new();
1002		/*
1003		 * Required by Linux initiator.
1004		 */
1005		auth_method = keys_find(request_keys, "AuthMethod");
1006		if (auth_method != NULL &&
1007		    login_list_contains(auth_method, "None"))
1008			keys_add(response_keys, "AuthMethod", "None");
1009
1010		if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
1011			if (conn->conn_target->t_alias != NULL)
1012				keys_add(response_keys,
1013				    "TargetAlias", conn->conn_target->t_alias);
1014			rv = asprintf(&portal_group_tag, "%d",
1015			    conn->conn_portal->p_portal_group->pg_tag);
1016			if (rv <= 0)
1017				log_err(1, "asprintf");
1018			keys_add(response_keys,
1019			    "TargetPortalGroupTag", portal_group_tag);
1020			free(portal_group_tag);
1021		}
1022		keys_save(response_keys, response);
1023		pdu_send(response);
1024		pdu_delete(response);
1025		keys_delete(response_keys);
1026		pdu_delete(request);
1027		keys_delete(request_keys);
1028
1029		login_negotiate(conn, NULL);
1030		return;
1031	}
1032
1033	if (ag->ag_type == AG_TYPE_DENY) {
1034		login_send_error(request, 0x02, 0x01);
1035		log_errx(1, "auth-group type is \"deny\"");
1036	}
1037
1038	if (ag->ag_type == AG_TYPE_UNKNOWN) {
1039		/*
1040		 * This can happen with empty auth-group.
1041		 */
1042		login_send_error(request, 0x02, 0x01);
1043		log_errx(1, "auth-group type not set, denying access");
1044	}
1045
1046	log_debugx("CHAP authentication required");
1047
1048	auth_method = keys_find(request_keys, "AuthMethod");
1049	if (auth_method == NULL) {
1050		login_send_error(request, 0x02, 0x07);
1051		log_errx(1, "received Login PDU without AuthMethod");
1052	}
1053	/*
1054	 * XXX: This should be Reject, not just a login failure (5.3.2).
1055	 */
1056	if (login_list_contains(auth_method, "CHAP") == 0) {
1057		login_send_error(request, 0x02, 0x01);
1058		log_errx(1, "initiator requests unsupported AuthMethod \"%s\" "
1059		    "instead of \"CHAP\"", auth_method);
1060	}
1061
1062	response = login_new_response(request);
1063
1064	response_keys = keys_new();
1065	keys_add(response_keys, "AuthMethod", "CHAP");
1066	if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
1067		rv = asprintf(&portal_group_tag, "%d",
1068		    conn->conn_portal->p_portal_group->pg_tag);
1069		if (rv <= 0)
1070			log_err(1, "asprintf");
1071		keys_add(response_keys,
1072		    "TargetPortalGroupTag", portal_group_tag);
1073		free(portal_group_tag);
1074		if (conn->conn_target->t_alias != NULL)
1075			keys_add(response_keys,
1076			    "TargetAlias", conn->conn_target->t_alias);
1077	}
1078	keys_save(response_keys, response);
1079
1080	pdu_send(response);
1081	pdu_delete(response);
1082	keys_delete(response_keys);
1083	pdu_delete(request);
1084	keys_delete(request_keys);
1085
1086	login_chap(conn, ag);
1087
1088	login_negotiate(conn, NULL);
1089}
1090