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