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 /*
|