]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - usr.sbin/iscsid/login.c
Remove empty sections.
[FreeBSD/releng/10.1.git] / usr.sbin / iscsid / login.c
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  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
36 #include <assert.h>
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <netinet/in.h>
42 #include <openssl/err.h>
43 #include <openssl/md5.h>
44 #include <openssl/rand.h>
45
46 #include "iscsid.h"
47 #include "iscsi_proto.h"
48
49 static int
50 login_nsg(const struct pdu *response)
51 {
52         struct iscsi_bhs_login_response *bhslr;
53
54         bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs;
55
56         return (bhslr->bhslr_flags & 0x03);
57 }
58
59 static void
60 login_set_nsg(struct pdu *request, int nsg)
61 {
62         struct iscsi_bhs_login_request *bhslr;
63
64         assert(nsg == BHSLR_STAGE_SECURITY_NEGOTIATION ||
65             nsg == BHSLR_STAGE_OPERATIONAL_NEGOTIATION ||
66             nsg == BHSLR_STAGE_FULL_FEATURE_PHASE);
67
68         bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
69
70         bhslr->bhslr_flags &= 0xFC;
71         bhslr->bhslr_flags |= nsg;
72 }
73
74 static void
75 login_set_csg(struct pdu *request, int csg)
76 {
77         struct iscsi_bhs_login_request *bhslr;
78
79         assert(csg == BHSLR_STAGE_SECURITY_NEGOTIATION ||
80             csg == BHSLR_STAGE_OPERATIONAL_NEGOTIATION ||
81             csg == BHSLR_STAGE_FULL_FEATURE_PHASE);
82
83         bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
84
85         bhslr->bhslr_flags &= 0xF3;
86         bhslr->bhslr_flags |= csg << 2;
87 }
88
89 static const char *
90 login_target_error_str(int class, int detail)
91 {
92         static char msg[128];
93
94         /*
95          * RFC 3270, 10.13.5.  Status-Class and Status-Detail
96          */
97         switch (class) {
98         case 0x01:
99                 switch (detail) {
100                 case 0x01:
101                         return ("Target moved temporarily");
102                 case 0x02:
103                         return ("Target moved permanently");
104                 default:
105                         snprintf(msg, sizeof(msg), "unknown redirection; "
106                             "Status-Class 0x%x, Status-Detail 0x%x",
107                             class, detail);
108                         return (msg);
109                 }
110         case 0x02:
111                 switch (detail) {
112                 case 0x00:
113                         return ("Initiator error");
114                 case 0x01:
115                         return ("Authentication failure");
116                 case 0x02:
117                         return ("Authorization failure");
118                 case 0x03:
119                         return ("Not found");
120                 case 0x04:
121                         return ("Target removed");
122                 case 0x05:
123                         return ("Unsupported version");
124                 case 0x06:
125                         return ("Too many connections");
126                 case 0x07:
127                         return ("Missing parameter");
128                 case 0x08:
129                         return ("Can't include in session");
130                 case 0x09:
131                         return ("Session type not supported");
132                 case 0x0a:
133                         return ("Session does not exist");
134                 case 0x0b:
135                         return ("Invalid during login");
136                 default:
137                         snprintf(msg, sizeof(msg), "unknown initiator error; "
138                             "Status-Class 0x%x, Status-Detail 0x%x",
139                             class, detail);
140                         return (msg);
141                 }
142         case 0x03:
143                 switch (detail) {
144                 case 0x00:
145                         return ("Target error");
146                 case 0x01:
147                         return ("Service unavailable");
148                 case 0x02:
149                         return ("Out of resources");
150                 default:
151                         snprintf(msg, sizeof(msg), "unknown target error; "
152                             "Status-Class 0x%x, Status-Detail 0x%x",
153                             class, detail);
154                         return (msg);
155                 }
156         default:
157                 snprintf(msg, sizeof(msg), "unknown error; "
158                     "Status-Class 0x%x, Status-Detail 0x%x",
159                     class, detail);
160                 return (msg);
161         }
162 }
163
164 static void
165 kernel_modify(const struct connection *conn, const char *target_address)
166 {
167         struct iscsi_session_modify ism;
168         int error;
169
170         memset(&ism, 0, sizeof(ism));
171         ism.ism_session_id = conn->conn_session_id;
172         memcpy(&ism.ism_conf, &conn->conn_conf, sizeof(ism.ism_conf));
173         strlcpy(ism.ism_conf.isc_target_addr, target_address,
174             sizeof(ism.ism_conf.isc_target));
175         error = ioctl(conn->conn_iscsi_fd, ISCSISMODIFY, &ism);
176         if (error != 0) {
177                 log_err(1, "failed to redirect to %s: ISCSISMODIFY",
178                     target_address);
179         }
180 }
181
182 /*
183  * XXX: The way it works is suboptimal; what should happen is described
184  *      in draft-gilligan-iscsi-fault-tolerance-00.  That, however, would
185  *      be much more complicated: we would need to keep "dependencies"
186  *      for sessions, so that, in case described in draft and using draft
187  *      terminology, we would have three sessions: one for discovery,
188  *      one for initial target portal, and one for redirect portal.  
189  *      This would allow us to "backtrack" on connection failure,
190  *      as described in draft.
191  */
192 static void
193 login_handle_redirection(struct connection *conn, struct pdu *response)
194 {
195         struct iscsi_bhs_login_response *bhslr;
196         struct keys *response_keys;
197         const char *target_address;
198
199         bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs;
200         assert (bhslr->bhslr_status_class == 1);
201
202         response_keys = keys_new();
203         keys_load(response_keys, response);
204
205         target_address = keys_find(response_keys, "TargetAddress");
206         if (target_address == NULL)
207                 log_errx(1, "received redirection without TargetAddress");
208         if (target_address[0] == '\0')
209                 log_errx(1, "received redirection with empty TargetAddress");
210         if (strlen(target_address) >=
211             sizeof(conn->conn_conf.isc_target_addr) - 1)
212                 log_errx(1, "received TargetAddress is too long");
213
214         log_debugx("received redirection to \"%s\"", target_address);
215         kernel_modify(conn, target_address);
216 }
217
218 static struct pdu *
219 login_receive(struct connection *conn)
220 {
221         struct pdu *response;
222         struct iscsi_bhs_login_response *bhslr;
223         const char *errorstr;
224         static bool initial = true;
225
226         response = pdu_new(conn);
227         pdu_receive(response);
228         if (response->pdu_bhs->bhs_opcode != ISCSI_BHS_OPCODE_LOGIN_RESPONSE) {
229                 log_errx(1, "protocol error: received invalid opcode 0x%x",
230                     response->pdu_bhs->bhs_opcode);
231         }
232         bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs;
233         /*
234          * XXX: Implement the C flag some day.
235          */
236         if ((bhslr->bhslr_flags & BHSLR_FLAGS_CONTINUE) != 0)
237                 log_errx(1, "received Login PDU with unsupported \"C\" flag");
238         if (bhslr->bhslr_version_max != 0x00)
239                 log_errx(1, "received Login PDU with unsupported "
240                     "Version-max 0x%x", bhslr->bhslr_version_max);
241         if (bhslr->bhslr_version_active != 0x00)
242                 log_errx(1, "received Login PDU with unsupported "
243                     "Version-active 0x%x", bhslr->bhslr_version_active);
244         if (bhslr->bhslr_status_class == 1) {
245                 login_handle_redirection(conn, response);
246                 log_debugx("redirection handled; exiting");
247                 exit(0);
248         }
249         if (bhslr->bhslr_status_class != 0) {
250                 errorstr = login_target_error_str(bhslr->bhslr_status_class,
251                     bhslr->bhslr_status_detail);
252                 fail(conn, errorstr);
253                 log_errx(1, "target returned error: %s", errorstr);
254         }
255         if (initial == false &&
256             ntohl(bhslr->bhslr_statsn) != conn->conn_statsn + 1) {
257                 /*
258                  * It's a warning, not an error, to work around what seems
259                  * to be bug in NetBSD iSCSI target.
260                  */
261                 log_warnx("received Login PDU with wrong StatSN: "
262                     "is %d, should be %d", ntohl(bhslr->bhslr_statsn),
263                     conn->conn_statsn + 1);
264         }
265         conn->conn_tsih = ntohs(bhslr->bhslr_tsih);
266         conn->conn_statsn = ntohl(bhslr->bhslr_statsn);
267
268         initial = false;
269
270         return (response);
271 }
272
273 static struct pdu *
274 login_new_request(struct connection *conn, int csg)
275 {
276         struct pdu *request;
277         struct iscsi_bhs_login_request *bhslr;
278         int nsg;
279
280         request = pdu_new(conn);
281         bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
282         bhslr->bhslr_opcode = ISCSI_BHS_OPCODE_LOGIN_REQUEST |
283             ISCSI_BHS_OPCODE_IMMEDIATE;
284
285         bhslr->bhslr_flags = BHSLR_FLAGS_TRANSIT;
286         switch (csg) {
287         case BHSLR_STAGE_SECURITY_NEGOTIATION:
288                 nsg = BHSLR_STAGE_OPERATIONAL_NEGOTIATION;
289                 break;
290         case BHSLR_STAGE_OPERATIONAL_NEGOTIATION:
291                 nsg = BHSLR_STAGE_FULL_FEATURE_PHASE;
292                 break;
293         default:
294                 assert(!"invalid csg");
295                 log_errx(1, "invalid csg %d", csg);
296         }
297         login_set_csg(request, csg);
298         login_set_nsg(request, nsg);
299
300         memcpy(bhslr->bhslr_isid, &conn->conn_isid, sizeof(bhslr->bhslr_isid));
301         bhslr->bhslr_tsih = htons(conn->conn_tsih);
302         bhslr->bhslr_initiator_task_tag = 0;
303         bhslr->bhslr_cmdsn = 0;
304         bhslr->bhslr_expstatsn = htonl(conn->conn_statsn + 1);
305
306         return (request);
307 }
308
309 static int
310 login_list_prefers(const char *list,
311     const char *choice1, const char *choice2)
312 {
313         char *tofree, *str, *token;
314
315         tofree = str = checked_strdup(list);
316
317         while ((token = strsep(&str, ",")) != NULL) {
318                 if (strcmp(token, choice1) == 0) {
319                         free(tofree);
320                         return (1);
321                 }
322                 if (strcmp(token, choice2) == 0) {
323                         free(tofree);
324                         return (2);
325                 }
326         }
327         free(tofree);
328         return (-1);
329 }
330
331 static int
332 login_hex2int(const char hex)
333 {
334         switch (hex) {
335         case '0':
336                 return (0x00);
337         case '1':
338                 return (0x01);
339         case '2':
340                 return (0x02);
341         case '3':
342                 return (0x03);
343         case '4':
344                 return (0x04);
345         case '5':
346                 return (0x05);
347         case '6':
348                 return (0x06);
349         case '7':
350                 return (0x07);
351         case '8':
352                 return (0x08);
353         case '9':
354                 return (0x09);
355         case 'a':
356         case 'A':
357                 return (0x0a);
358         case 'b':
359         case 'B':
360                 return (0x0b);
361         case 'c':
362         case 'C':
363                 return (0x0c);
364         case 'd':
365         case 'D':
366                 return (0x0d);
367         case 'e':
368         case 'E':
369                 return (0x0e);
370         case 'f':
371         case 'F':
372                 return (0x0f);
373         default:
374                 return (-1);
375         }
376 }
377
378 /*
379  * XXX: Review this _carefully_.
380  */
381 static int
382 login_hex2bin(const char *hex, char **binp, size_t *bin_lenp)
383 {
384         int i, hex_len, nibble;
385         bool lo = true; /* As opposed to 'hi'. */
386         char *bin;
387         size_t bin_off, bin_len;
388
389         if (strncasecmp(hex, "0x", strlen("0x")) != 0) {
390                 log_warnx("malformed variable, should start with \"0x\"");
391                 return (-1);
392         }
393
394         hex += strlen("0x");
395         hex_len = strlen(hex);
396         if (hex_len < 1) {
397                 log_warnx("malformed variable; doesn't contain anything "
398                     "but \"0x\"");
399                 return (-1);
400         }
401
402         bin_len = hex_len / 2 + hex_len % 2;
403         bin = calloc(bin_len, 1);
404         if (bin == NULL)
405                 log_err(1, "calloc");
406
407         bin_off = bin_len - 1;
408         for (i = hex_len - 1; i >= 0; i--) {
409                 nibble = login_hex2int(hex[i]);
410                 if (nibble < 0) {
411                         log_warnx("malformed variable, invalid char \"%c\"",
412                             hex[i]);
413                         return (-1);
414                 }
415
416                 assert(bin_off < bin_len);
417                 if (lo) {
418                         bin[bin_off] = nibble;
419                         lo = false;
420                 } else {
421                         bin[bin_off] |= nibble << 4;
422                         bin_off--;
423                         lo = true;
424                 }
425         }
426
427         *binp = bin;
428         *bin_lenp = bin_len;
429         return (0);
430 }
431
432 static char *
433 login_bin2hex(const char *bin, size_t bin_len)
434 {
435         unsigned char *hex, *tmp, ch;
436         size_t hex_len;
437         size_t i;
438
439         hex_len = bin_len * 2 + 3; /* +2 for "0x", +1 for '\0'. */
440         hex = malloc(hex_len);
441         if (hex == NULL)
442                 log_err(1, "malloc");
443
444         tmp = hex;
445         tmp += sprintf(tmp, "0x");
446         for (i = 0; i < bin_len; i++) {
447                 ch = bin[i];
448                 tmp += sprintf(tmp, "%02x", ch);
449         }
450
451         return (hex);
452 }
453
454 static void
455 login_compute_md5(const char id, const char *secret,
456     const void *challenge, size_t challenge_len, void *response,
457     size_t response_len)
458 {
459         MD5_CTX ctx;
460         int rv;
461
462         assert(response_len == MD5_DIGEST_LENGTH);
463
464         MD5_Init(&ctx);
465         MD5_Update(&ctx, &id, sizeof(id));
466         MD5_Update(&ctx, secret, strlen(secret));
467         MD5_Update(&ctx, challenge, challenge_len);
468         rv = MD5_Final(response, &ctx);
469         if (rv != 1)
470                 log_errx(1, "MD5_Final");
471 }
472
473 static void
474 login_negotiate_key(struct connection *conn, const char *name,
475     const char *value)
476 {
477         int which, tmp;
478
479         if (strcmp(name, "TargetAlias") == 0) {
480                 strlcpy(conn->conn_target_alias, value,
481                     sizeof(conn->conn_target_alias));
482         } else if (strcmp(value, "Irrelevant") == 0) {
483                 /* Ignore. */
484         } else if (strcmp(name, "HeaderDigest") == 0) {
485                 which = login_list_prefers(value, "CRC32C", "None");
486                 switch (which) {
487                 case 1:
488                         log_debugx("target prefers CRC32C "
489                             "for header digest; we'll use it");
490                         conn->conn_header_digest = CONN_DIGEST_CRC32C;
491                         break;
492                 case 2:
493                         log_debugx("target prefers not to do "
494                             "header digest; we'll comply");
495                         break;
496                 default:
497                         log_warnx("target sent unrecognized "
498                             "HeaderDigest value \"%s\"; will use None", value);
499                         break;
500                 }
501         } else if (strcmp(name, "DataDigest") == 0) {
502                 which = login_list_prefers(value, "CRC32C", "None");
503                 switch (which) {
504                 case 1:
505                         log_debugx("target prefers CRC32C "
506                             "for data digest; we'll use it");
507                         conn->conn_data_digest = CONN_DIGEST_CRC32C;
508                         break;
509                 case 2:
510                         log_debugx("target prefers not to do "
511                             "data digest; we'll comply");
512                         break;
513                 default:
514                         log_warnx("target sent unrecognized "
515                             "DataDigest value \"%s\"; will use None", value);
516                         break;
517                 }
518         } else if (strcmp(name, "MaxConnections") == 0) {
519                 /* Ignore. */
520         } else if (strcmp(name, "InitialR2T") == 0) {
521                 if (strcmp(value, "Yes") == 0)
522                         conn->conn_initial_r2t = true;
523                 else
524                         conn->conn_initial_r2t = false;
525         } else if (strcmp(name, "ImmediateData") == 0) {
526                 if (strcmp(value, "Yes") == 0)
527                         conn->conn_immediate_data = true;
528                 else
529                         conn->conn_immediate_data = false;
530         } else if (strcmp(name, "MaxRecvDataSegmentLength") == 0) {
531                 tmp = strtoul(value, NULL, 10);
532                 if (tmp <= 0)
533                         log_errx(1, "received invalid "
534                             "MaxRecvDataSegmentLength");
535                 conn->conn_max_data_segment_length = tmp;
536         } else if (strcmp(name, "MaxBurstLength") == 0) {
537                 if (conn->conn_immediate_data) {
538                         tmp = strtoul(value, NULL, 10);
539                         if (tmp <= 0)
540                                 log_errx(1, "received invalid MaxBurstLength");
541                         conn->conn_max_burst_length = tmp;
542                 }
543         } else if (strcmp(name, "FirstBurstLength") == 0) {
544                 tmp = strtoul(value, NULL, 10);
545                 if (tmp <= 0)
546                         log_errx(1, "received invalid FirstBurstLength");
547                 conn->conn_first_burst_length = tmp;
548         } else if (strcmp(name, "DefaultTime2Wait") == 0) {
549                 /* Ignore */
550         } else if (strcmp(name, "DefaultTime2Retain") == 0) {
551                 /* Ignore */
552         } else if (strcmp(name, "MaxOutstandingR2T") == 0) {
553                 /* Ignore */
554         } else if (strcmp(name, "DataPDUInOrder") == 0) {
555                 /* Ignore */
556         } else if (strcmp(name, "DataSequenceInOrder") == 0) {
557                 /* Ignore */
558         } else if (strcmp(name, "ErrorRecoveryLevel") == 0) {
559                 /* Ignore */
560         } else if (strcmp(name, "OFMarker") == 0) {
561                 /* Ignore */
562         } else if (strcmp(name, "IFMarker") == 0) {
563                 /* Ignore */
564         } else if (strcmp(name, "TargetPortalGroupTag") == 0) {
565                 /* Ignore */
566         } else {
567                 log_debugx("unknown key \"%s\"; ignoring",  name);
568         }
569 }
570
571 static void
572 login_negotiate(struct connection *conn)
573 {
574         struct pdu *request, *response;
575         struct keys *request_keys, *response_keys;
576         struct iscsi_bhs_login_response *bhslr;
577         int i, nrequests = 0;
578
579         log_debugx("beginning operational parameter negotiation");
580         request = login_new_request(conn, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
581         request_keys = keys_new();
582
583         /*
584          * The following keys are irrelevant for discovery sessions.
585          */
586         if (conn->conn_conf.isc_discovery == 0) {
587                 if (conn->conn_conf.isc_header_digest != 0)
588                         keys_add(request_keys, "HeaderDigest", "CRC32C");
589                 else
590                         keys_add(request_keys, "HeaderDigest", "None");
591                 if (conn->conn_conf.isc_data_digest != 0)
592                         keys_add(request_keys, "DataDigest", "CRC32C");
593                 else
594                         keys_add(request_keys, "DataDigest", "None");
595
596                 keys_add(request_keys, "ImmediateData", "Yes");
597                 keys_add_int(request_keys, "MaxBurstLength",
598                     ISCSI_MAX_DATA_SEGMENT_LENGTH);
599                 keys_add_int(request_keys, "FirstBurstLength",
600                     ISCSI_MAX_DATA_SEGMENT_LENGTH);
601                 keys_add(request_keys, "InitialR2T", "Yes");
602         } else {
603                 keys_add(request_keys, "HeaderDigest", "None");
604                 keys_add(request_keys, "DataDigest", "None");
605         }
606
607         keys_add_int(request_keys, "MaxRecvDataSegmentLength",
608             ISCSI_MAX_DATA_SEGMENT_LENGTH);
609         keys_add(request_keys, "DefaultTime2Wait", "0");
610         keys_add(request_keys, "DefaultTime2Retain", "0");
611         keys_add(request_keys, "ErrorRecoveryLevel", "0");
612         keys_add(request_keys, "MaxOutstandingR2T", "1");
613         keys_save(request_keys, request);
614         keys_delete(request_keys);
615         request_keys = NULL;
616         pdu_send(request);
617         pdu_delete(request);
618         request = NULL;
619
620         response = login_receive(conn);
621         response_keys = keys_new();
622         keys_load(response_keys, response);
623         for (i = 0; i < KEYS_MAX; i++) {
624                 if (response_keys->keys_names[i] == NULL)
625                         break;
626
627                 login_negotiate_key(conn,
628                     response_keys->keys_names[i], response_keys->keys_values[i]);
629         }
630
631         keys_delete(response_keys);
632         response_keys = NULL;
633
634         for (;;) {
635                 bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs;
636                 if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) != 0)
637                         break;
638
639                 nrequests++;
640                 if (nrequests > 5) {
641                         log_warnx("received login response "
642                             "without the \"T\" flag too many times; giving up");
643                         break;
644                 }
645
646                 log_debugx("received login response "
647                     "without the \"T\" flag; sending another request");
648
649                 pdu_delete(response);
650
651                 request = login_new_request(conn,
652                     BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
653                 pdu_send(request);
654                 pdu_delete(request);
655
656                 response = login_receive(conn);
657         }
658
659         if (login_nsg(response) != BHSLR_STAGE_FULL_FEATURE_PHASE)
660                 log_warnx("received final login response with wrong NSG 0x%x",
661                     login_nsg(response));
662         pdu_delete(response);
663
664         log_debugx("operational parameter negotiation done; "
665             "transitioning to Full Feature phase");
666 }
667
668 static void
669 login_send_chap_a(struct connection *conn)
670 {
671         struct pdu *request;
672         struct keys *request_keys;
673
674         request = login_new_request(conn, BHSLR_STAGE_SECURITY_NEGOTIATION);
675         request_keys = keys_new();
676         keys_add(request_keys, "CHAP_A", "5");
677         keys_save(request_keys, request);
678         keys_delete(request_keys);
679         pdu_send(request);
680         pdu_delete(request);
681 }
682
683 static void
684 login_send_chap_r(struct pdu *response)
685 {
686         struct connection *conn;
687         struct pdu *request;
688         struct keys *request_keys, *response_keys;
689         const char *chap_a, *chap_c, *chap_i;
690         char *chap_r, *challenge, response_bin[MD5_DIGEST_LENGTH];
691         size_t challenge_len;
692         int error, rv;
693         unsigned char id;
694         char *mutual_chap_c, mutual_chap_i[4];
695
696         /*
697          * As in the rest of the initiator, 'request' means
698          * 'initiator -> target', and 'response' means 'target -> initiator',
699          *
700          * So, here the 'response' from the target is the packet that contains
701          * CHAP challenge; our CHAP response goes into 'request'.
702          */
703
704         conn = response->pdu_connection;
705
706         response_keys = keys_new();
707         keys_load(response_keys, response);
708
709         /*
710          * First, compute the response.
711          */
712         chap_a = keys_find(response_keys, "CHAP_A");
713         if (chap_a == NULL)
714                 log_errx(1, "received CHAP packet without CHAP_A");
715         chap_c = keys_find(response_keys, "CHAP_C");
716         if (chap_c == NULL)
717                 log_errx(1, "received CHAP packet without CHAP_C");
718         chap_i = keys_find(response_keys, "CHAP_I");
719         if (chap_i == NULL)
720                 log_errx(1, "received CHAP packet without CHAP_I");
721
722         if (strcmp(chap_a, "5") != 0)
723                 log_errx(1, "received CHAP packet "
724                     "with unsupported CHAP_A \"%s\"", chap_a);
725         id = strtoul(chap_i, NULL, 10);
726         error = login_hex2bin(chap_c, &challenge, &challenge_len);
727         if (error != 0)
728                 log_errx(1, "received CHAP packet with malformed CHAP_C");
729         login_compute_md5(id, conn->conn_conf.isc_secret,
730             challenge, challenge_len, response_bin, sizeof(response_bin));
731         free(challenge);
732         chap_r = login_bin2hex(response_bin, sizeof(response_bin));
733
734         keys_delete(response_keys);
735
736         request = login_new_request(conn, BHSLR_STAGE_SECURITY_NEGOTIATION);
737         request_keys = keys_new();
738         keys_add(request_keys, "CHAP_N", conn->conn_conf.isc_user);
739         keys_add(request_keys, "CHAP_R", chap_r);
740         free(chap_r);
741
742         /*
743          * If we want mutual authentication, we're expected to send
744          * our CHAP_I/CHAP_C now.
745          */
746         if (conn->conn_conf.isc_mutual_user[0] != '\0') {
747                 log_debugx("requesting mutual authentication; "
748                     "binary challenge size is %zd bytes",
749                     sizeof(conn->conn_mutual_challenge));
750
751                 rv = RAND_bytes(conn->conn_mutual_challenge,
752                     sizeof(conn->conn_mutual_challenge));
753                 if (rv != 1) {
754                         log_errx(1, "RAND_bytes failed: %s",
755                             ERR_error_string(ERR_get_error(), NULL));
756                 }
757                 rv = RAND_bytes(&conn->conn_mutual_id,
758                     sizeof(conn->conn_mutual_id));
759                 if (rv != 1) {
760                         log_errx(1, "RAND_bytes failed: %s",
761                             ERR_error_string(ERR_get_error(), NULL));
762                 }
763                 mutual_chap_c = login_bin2hex(conn->conn_mutual_challenge,
764                     sizeof(conn->conn_mutual_challenge));
765                 snprintf(mutual_chap_i, sizeof(mutual_chap_i),
766                     "%d", conn->conn_mutual_id);
767                 keys_add(request_keys, "CHAP_I", mutual_chap_i);
768                 keys_add(request_keys, "CHAP_C", mutual_chap_c);
769                 free(mutual_chap_c);
770         }
771
772         keys_save(request_keys, request);
773         keys_delete(request_keys);
774         pdu_send(request);
775         pdu_delete(request);
776 }
777
778 static void
779 login_verify_mutual(const struct pdu *response)
780 {
781         struct connection *conn;
782         struct keys *response_keys;
783         const char *chap_n, *chap_r;
784         char *response_bin, expected_response_bin[MD5_DIGEST_LENGTH];
785         size_t response_bin_len;
786         int error;
787
788         conn = response->pdu_connection;
789
790         response_keys = keys_new();
791         keys_load(response_keys, response);
792
793         chap_n = keys_find(response_keys, "CHAP_N");
794         if (chap_n == NULL)
795                 log_errx(1, "received CHAP Response PDU without CHAP_N");
796         chap_r = keys_find(response_keys, "CHAP_R");
797         if (chap_r == NULL)
798                 log_errx(1, "received CHAP Response PDU without CHAP_R");
799         error = login_hex2bin(chap_r, &response_bin, &response_bin_len);
800         if (error != 0)
801                 log_errx(1, "received CHAP Response PDU with malformed CHAP_R");
802
803         if (strcmp(chap_n, conn->conn_conf.isc_mutual_user) != 0) {
804                 fail(conn, "Mutual CHAP failed");
805                 log_errx(1, "mutual CHAP authentication failed: wrong user");
806         }
807
808         login_compute_md5(conn->conn_mutual_id,
809             conn->conn_conf.isc_mutual_secret, conn->conn_mutual_challenge,
810             sizeof(conn->conn_mutual_challenge), expected_response_bin,
811             sizeof(expected_response_bin));
812
813         if (memcmp(response_bin, expected_response_bin,
814             sizeof(expected_response_bin)) != 0) {
815                 fail(conn, "Mutual CHAP failed");
816                 log_errx(1, "mutual CHAP authentication failed: wrong secret");
817         }
818
819         keys_delete(response_keys);
820         free(response_bin);
821
822         log_debugx("mutual CHAP authentication succeeded");
823 }
824
825 static void
826 login_chap(struct connection *conn)
827 {
828         struct pdu *response;
829
830         log_debugx("beginning CHAP authentication; sending CHAP_A");
831         login_send_chap_a(conn);
832
833         log_debugx("waiting for CHAP_A/CHAP_C/CHAP_I");
834         response = login_receive(conn);
835
836         log_debugx("sending CHAP_N/CHAP_R");
837         login_send_chap_r(response);
838         pdu_delete(response);
839
840         /*
841          * XXX: Make sure this is not susceptible to MITM.
842          */
843
844         log_debugx("waiting for CHAP result");
845         response = login_receive(conn);
846         if (conn->conn_conf.isc_mutual_user[0] != '\0')
847                 login_verify_mutual(response);
848         pdu_delete(response);
849
850         log_debugx("CHAP authentication done");
851 }
852
853 void
854 login(struct connection *conn)
855 {
856         struct pdu *request, *response;
857         struct keys *request_keys, *response_keys;
858         struct iscsi_bhs_login_response *bhslr2;
859         const char *auth_method;
860         int i;
861
862         log_debugx("beginning Login phase; sending Login PDU");
863         request = login_new_request(conn, BHSLR_STAGE_SECURITY_NEGOTIATION);
864         request_keys = keys_new();
865         if (conn->conn_conf.isc_mutual_user[0] != '\0') {
866                 keys_add(request_keys, "AuthMethod", "CHAP");
867         } else if (conn->conn_conf.isc_user[0] != '\0') {
868                 /*
869                  * Give target a chance to skip authentication if it
870                  * doesn't feel like it.
871                  *
872                  * None is first, CHAP second; this is to work around
873                  * what seems to be LIO (Linux target) bug: otherwise,
874                  * if target is configured with no authentication,
875                  * and we are configured to authenticate, the target
876                  * will erroneously respond with AuthMethod=CHAP
877                  * instead of AuthMethod=None, and will subsequently
878                  * fail the connection.  This usually happens with
879                  * Discovery sessions, which default to no authentication.
880                  */
881                 keys_add(request_keys, "AuthMethod", "None,CHAP");
882         } else {
883                 keys_add(request_keys, "AuthMethod", "None");
884         }
885         keys_add(request_keys, "InitiatorName",
886             conn->conn_conf.isc_initiator);
887         if (conn->conn_conf.isc_initiator_alias[0] != '\0') {
888                 keys_add(request_keys, "InitiatorAlias",
889                     conn->conn_conf.isc_initiator_alias);
890         }
891         if (conn->conn_conf.isc_discovery == 0) {
892                 keys_add(request_keys, "SessionType", "Normal");
893                 keys_add(request_keys,
894                     "TargetName", conn->conn_conf.isc_target);
895         } else {
896                 keys_add(request_keys, "SessionType", "Discovery");
897         }
898         keys_save(request_keys, request);
899         keys_delete(request_keys);
900         pdu_send(request);
901         pdu_delete(request);
902
903         response = login_receive(conn);
904
905         response_keys = keys_new();
906         keys_load(response_keys, response);
907
908         for (i = 0; i < KEYS_MAX; i++) {
909                 if (response_keys->keys_names[i] == NULL)
910                         break;
911
912                 /*
913                  * Not interested in AuthMethod at this point; we only need
914                  * to parse things such as TargetAlias.
915                  *
916                  * XXX: This is somewhat ugly.  We should have a way to apply
917                  *      all the keys to the session and use that by default
918                  *      instead of discarding them.
919                  */
920                 if (strcmp(response_keys->keys_names[i], "AuthMethod") == 0)
921                         continue;
922
923                 login_negotiate_key(conn,
924                     response_keys->keys_names[i], response_keys->keys_values[i]);
925         }
926
927         bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
928         if ((bhslr2->bhslr_flags & BHSLR_FLAGS_TRANSIT) != 0 &&
929             login_nsg(response) == BHSLR_STAGE_OPERATIONAL_NEGOTIATION) {
930                 if (conn->conn_conf.isc_mutual_user[0] != '\0') {
931                         log_errx(1, "target requested transition "
932                             "to operational parameter negotiation, "
933                             "but we require mutual CHAP");
934                 }
935
936                 log_debugx("target requested transition "
937                     "to operational parameter negotiation");
938                 keys_delete(response_keys);
939                 pdu_delete(response);
940                 login_negotiate(conn);
941                 return;
942         }
943
944         auth_method = keys_find(response_keys, "AuthMethod");
945         if (auth_method == NULL)
946                 log_errx(1, "received response without AuthMethod");
947         if (strcmp(auth_method, "None") == 0) {
948                 if (conn->conn_conf.isc_mutual_user[0] != '\0') {
949                         log_errx(1, "target does not require authantication, "
950                             "but we require mutual CHAP");
951                 }
952
953                 log_debugx("target does not require authentication");
954                 keys_delete(response_keys);
955                 pdu_delete(response);
956                 login_negotiate(conn);
957                 return;
958         }
959
960         if (strcmp(auth_method, "CHAP") != 0) {
961                 fail(conn, "Unsupported AuthMethod");
962                 log_errx(1, "received response "
963                     "with unsupported AuthMethod \"%s\"", auth_method);
964         }
965
966         if (conn->conn_conf.isc_user[0] == '\0' ||
967             conn->conn_conf.isc_secret[0] == '\0') {
968                 fail(conn, "Authentication required");
969                 log_errx(1, "target requests CHAP authentication, but we don't "
970                     "have user and secret");
971         }
972
973         keys_delete(response_keys);
974         response_keys = NULL;
975         pdu_delete(response);
976         response = NULL;
977
978         login_chap(conn);
979         login_negotiate(conn);
980 }