1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /******************************************************************************* |
3 | * This file contains main functions related to iSCSI Parameter negotiation. |
4 | * |
5 | * (c) Copyright 2007-2013 Datera, Inc. |
6 | * |
7 | * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> |
8 | * |
9 | ******************************************************************************/ |
10 | |
11 | #include <linux/ctype.h> |
12 | #include <linux/kthread.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/sched/signal.h> |
15 | #include <net/sock.h> |
16 | #include <trace/events/sock.h> |
17 | #include <scsi/iscsi_proto.h> |
18 | #include <target/target_core_base.h> |
19 | #include <target/target_core_fabric.h> |
20 | #include <target/iscsi/iscsi_transport.h> |
21 | |
22 | #include <target/iscsi/iscsi_target_core.h> |
23 | #include "iscsi_target_parameters.h" |
24 | #include "iscsi_target_login.h" |
25 | #include "iscsi_target_nego.h" |
26 | #include "iscsi_target_tpg.h" |
27 | #include "iscsi_target_util.h" |
28 | #include "iscsi_target.h" |
29 | #include "iscsi_target_auth.h" |
30 | |
31 | #define MAX_LOGIN_PDUS 7 |
32 | |
33 | void convert_null_to_semi(char *buf, int len) |
34 | { |
35 | int i; |
36 | |
37 | for (i = 0; i < len; i++) |
38 | if (buf[i] == '\0') |
39 | buf[i] = ';'; |
40 | } |
41 | |
42 | static int strlen_semi(char *buf) |
43 | { |
44 | int i = 0; |
45 | |
46 | while (buf[i] != '\0') { |
47 | if (buf[i] == ';') |
48 | return i; |
49 | i++; |
50 | } |
51 | |
52 | return -1; |
53 | } |
54 | |
55 | int ( |
56 | const char *in_buf, |
57 | const char *pattern, |
58 | unsigned int max_length, |
59 | char *out_buf, |
60 | unsigned char *type) |
61 | { |
62 | char *ptr; |
63 | int len; |
64 | |
65 | if (!in_buf || !pattern || !out_buf || !type) |
66 | return -EINVAL; |
67 | |
68 | ptr = strstr(in_buf, pattern); |
69 | if (!ptr) |
70 | return -ENOENT; |
71 | |
72 | ptr = strstr(ptr, "=" ); |
73 | if (!ptr) |
74 | return -EINVAL; |
75 | |
76 | ptr += 1; |
77 | if (*ptr == '0' && (*(ptr+1) == 'x' || *(ptr+1) == 'X')) { |
78 | ptr += 2; /* skip 0x */ |
79 | *type = HEX; |
80 | } else if (*ptr == '0' && (*(ptr+1) == 'b' || *(ptr+1) == 'B')) { |
81 | ptr += 2; /* skip 0b */ |
82 | *type = BASE64; |
83 | } else |
84 | *type = DECIMAL; |
85 | |
86 | len = strlen_semi(buf: ptr); |
87 | if (len < 0) |
88 | return -EINVAL; |
89 | |
90 | if (len >= max_length) { |
91 | pr_err("Length of input: %d exceeds max_length:" |
92 | " %d\n" , len, max_length); |
93 | return -EINVAL; |
94 | } |
95 | memcpy(out_buf, ptr, len); |
96 | out_buf[len] = '\0'; |
97 | |
98 | return 0; |
99 | } |
100 | |
101 | static struct iscsi_node_auth *iscsi_get_node_auth(struct iscsit_conn *conn) |
102 | { |
103 | struct iscsi_portal_group *tpg; |
104 | struct iscsi_node_acl *nacl; |
105 | struct se_node_acl *se_nacl; |
106 | |
107 | if (conn->sess->sess_ops->SessionType) |
108 | return &iscsit_global->discovery_acl.node_auth; |
109 | |
110 | se_nacl = conn->sess->se_sess->se_node_acl; |
111 | if (!se_nacl) { |
112 | pr_err("Unable to locate struct se_node_acl for CHAP auth\n" ); |
113 | return NULL; |
114 | } |
115 | |
116 | if (se_nacl->dynamic_node_acl) { |
117 | tpg = to_iscsi_tpg(se_tpg: se_nacl->se_tpg); |
118 | return &tpg->tpg_demo_auth; |
119 | } |
120 | |
121 | nacl = to_iscsi_nacl(se_nacl); |
122 | |
123 | return &nacl->node_auth; |
124 | } |
125 | |
126 | static u32 iscsi_handle_authentication( |
127 | struct iscsit_conn *conn, |
128 | char *in_buf, |
129 | char *out_buf, |
130 | int in_length, |
131 | int *out_length, |
132 | unsigned char *authtype) |
133 | { |
134 | struct iscsi_node_auth *auth; |
135 | |
136 | auth = iscsi_get_node_auth(conn); |
137 | if (!auth) |
138 | return -1; |
139 | |
140 | if (strstr("CHAP" , authtype)) |
141 | strcpy(p: conn->sess->auth_type, q: "CHAP" ); |
142 | else |
143 | strcpy(p: conn->sess->auth_type, NONE); |
144 | |
145 | if (strstr("None" , authtype)) |
146 | return 1; |
147 | else if (strstr("CHAP" , authtype)) |
148 | return chap_main_loop(conn, auth, in_buf, out_buf, |
149 | &in_length, out_length); |
150 | /* SRP, SPKM1, SPKM2 and KRB5 are unsupported */ |
151 | return 2; |
152 | } |
153 | |
154 | static void iscsi_remove_failed_auth_entry(struct iscsit_conn *conn) |
155 | { |
156 | kfree(objp: conn->auth_protocol); |
157 | } |
158 | |
159 | int iscsi_target_check_login_request( |
160 | struct iscsit_conn *conn, |
161 | struct iscsi_login *login) |
162 | { |
163 | int req_csg, req_nsg; |
164 | u32 payload_length; |
165 | struct iscsi_login_req *login_req; |
166 | |
167 | login_req = (struct iscsi_login_req *) login->req; |
168 | payload_length = ntoh24(login_req->dlength); |
169 | |
170 | switch (login_req->opcode & ISCSI_OPCODE_MASK) { |
171 | case ISCSI_OP_LOGIN: |
172 | break; |
173 | default: |
174 | pr_err("Received unknown opcode 0x%02x.\n" , |
175 | login_req->opcode & ISCSI_OPCODE_MASK); |
176 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
177 | ISCSI_LOGIN_STATUS_INIT_ERR); |
178 | return -1; |
179 | } |
180 | |
181 | if ((login_req->flags & ISCSI_FLAG_LOGIN_CONTINUE) && |
182 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { |
183 | pr_err("Login request has both ISCSI_FLAG_LOGIN_CONTINUE" |
184 | " and ISCSI_FLAG_LOGIN_TRANSIT set, protocol error.\n" ); |
185 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
186 | ISCSI_LOGIN_STATUS_INIT_ERR); |
187 | return -1; |
188 | } |
189 | |
190 | req_csg = ISCSI_LOGIN_CURRENT_STAGE(login_req->flags); |
191 | req_nsg = ISCSI_LOGIN_NEXT_STAGE(login_req->flags); |
192 | |
193 | if (req_csg != login->current_stage) { |
194 | pr_err("Initiator unexpectedly changed login stage" |
195 | " from %d to %d, login failed.\n" , login->current_stage, |
196 | req_csg); |
197 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
198 | ISCSI_LOGIN_STATUS_INIT_ERR); |
199 | return -1; |
200 | } |
201 | |
202 | if ((req_nsg == 2) || (req_csg >= 2) || |
203 | ((login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT) && |
204 | (req_nsg <= req_csg))) { |
205 | pr_err("Illegal login_req->flags Combination, CSG: %d," |
206 | " NSG: %d, ISCSI_FLAG_LOGIN_TRANSIT: %d.\n" , req_csg, |
207 | req_nsg, (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)); |
208 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
209 | ISCSI_LOGIN_STATUS_INIT_ERR); |
210 | return -1; |
211 | } |
212 | |
213 | if ((login_req->max_version != login->version_max) || |
214 | (login_req->min_version != login->version_min)) { |
215 | pr_err("Login request changed Version Max/Nin" |
216 | " unexpectedly to 0x%02x/0x%02x, protocol error\n" , |
217 | login_req->max_version, login_req->min_version); |
218 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
219 | ISCSI_LOGIN_STATUS_INIT_ERR); |
220 | return -1; |
221 | } |
222 | |
223 | if (memcmp(p: login_req->isid, q: login->isid, size: 6) != 0) { |
224 | pr_err("Login request changed ISID unexpectedly," |
225 | " protocol error.\n" ); |
226 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
227 | ISCSI_LOGIN_STATUS_INIT_ERR); |
228 | return -1; |
229 | } |
230 | |
231 | if (login_req->itt != login->init_task_tag) { |
232 | pr_err("Login request changed ITT unexpectedly to" |
233 | " 0x%08x, protocol error.\n" , login_req->itt); |
234 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
235 | ISCSI_LOGIN_STATUS_INIT_ERR); |
236 | return -1; |
237 | } |
238 | |
239 | if (payload_length > MAX_KEY_VALUE_PAIRS) { |
240 | pr_err("Login request payload exceeds default" |
241 | " MaxRecvDataSegmentLength: %u, protocol error.\n" , |
242 | MAX_KEY_VALUE_PAIRS); |
243 | return -1; |
244 | } |
245 | |
246 | return 0; |
247 | } |
248 | EXPORT_SYMBOL(iscsi_target_check_login_request); |
249 | |
250 | static int iscsi_target_check_first_request( |
251 | struct iscsit_conn *conn, |
252 | struct iscsi_login *login) |
253 | { |
254 | struct iscsi_param *param = NULL; |
255 | struct se_node_acl *se_nacl; |
256 | |
257 | login->first_request = 0; |
258 | |
259 | list_for_each_entry(param, &conn->param_list->param_list, p_list) { |
260 | if (!strncmp(param->name, SESSIONTYPE, 11)) { |
261 | if (!IS_PSTATE_ACCEPTOR(param)) { |
262 | pr_err("SessionType key not received" |
263 | " in first login request.\n" ); |
264 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
265 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); |
266 | return -1; |
267 | } |
268 | if (!strncmp(param->value, DISCOVERY, 9)) |
269 | return 0; |
270 | } |
271 | |
272 | if (!strncmp(param->name, INITIATORNAME, 13)) { |
273 | if (!IS_PSTATE_ACCEPTOR(param)) { |
274 | if (!login->leading_connection) |
275 | continue; |
276 | |
277 | pr_err("InitiatorName key not received" |
278 | " in first login request.\n" ); |
279 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
280 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); |
281 | return -1; |
282 | } |
283 | |
284 | /* |
285 | * For non-leading connections, double check that the |
286 | * received InitiatorName matches the existing session's |
287 | * struct iscsi_node_acl. |
288 | */ |
289 | if (!login->leading_connection) { |
290 | se_nacl = conn->sess->se_sess->se_node_acl; |
291 | if (!se_nacl) { |
292 | pr_err("Unable to locate" |
293 | " struct se_node_acl\n" ); |
294 | iscsit_tx_login_rsp(conn, |
295 | ISCSI_STATUS_CLS_INITIATOR_ERR, |
296 | ISCSI_LOGIN_STATUS_TGT_NOT_FOUND); |
297 | return -1; |
298 | } |
299 | |
300 | if (strcmp(param->value, |
301 | se_nacl->initiatorname)) { |
302 | pr_err("Incorrect" |
303 | " InitiatorName: %s for this" |
304 | " iSCSI Initiator Node.\n" , |
305 | param->value); |
306 | iscsit_tx_login_rsp(conn, |
307 | ISCSI_STATUS_CLS_INITIATOR_ERR, |
308 | ISCSI_LOGIN_STATUS_TGT_NOT_FOUND); |
309 | return -1; |
310 | } |
311 | } |
312 | } |
313 | } |
314 | |
315 | return 0; |
316 | } |
317 | |
318 | static int iscsi_target_do_tx_login_io(struct iscsit_conn *conn, struct iscsi_login *login) |
319 | { |
320 | u32 padding = 0; |
321 | struct iscsi_login_rsp *login_rsp; |
322 | |
323 | login_rsp = (struct iscsi_login_rsp *) login->rsp; |
324 | |
325 | login_rsp->opcode = ISCSI_OP_LOGIN_RSP; |
326 | hton24(login_rsp->dlength, login->rsp_length); |
327 | memcpy(login_rsp->isid, login->isid, 6); |
328 | login_rsp->tsih = cpu_to_be16(login->tsih); |
329 | login_rsp->itt = login->init_task_tag; |
330 | login_rsp->statsn = cpu_to_be32(conn->stat_sn++); |
331 | login_rsp->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); |
332 | login_rsp->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); |
333 | |
334 | pr_debug("Sending Login Response, Flags: 0x%02x, ITT: 0x%08x," |
335 | " ExpCmdSN; 0x%08x, MaxCmdSN: 0x%08x, StatSN: 0x%08x, Length:" |
336 | " %u\n" , login_rsp->flags, (__force u32)login_rsp->itt, |
337 | ntohl(login_rsp->exp_cmdsn), ntohl(login_rsp->max_cmdsn), |
338 | ntohl(login_rsp->statsn), login->rsp_length); |
339 | |
340 | padding = ((-login->rsp_length) & 3); |
341 | /* |
342 | * Before sending the last login response containing the transition |
343 | * bit for full-feature-phase, go ahead and start up TX/RX threads |
344 | * now to avoid potential resource allocation failures after the |
345 | * final login response has been sent. |
346 | */ |
347 | if (login->login_complete) { |
348 | int rc = iscsit_start_kthreads(conn); |
349 | if (rc) { |
350 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, |
351 | ISCSI_LOGIN_STATUS_NO_RESOURCES); |
352 | return -1; |
353 | } |
354 | } |
355 | |
356 | if (conn->conn_transport->iscsit_put_login_tx(conn, login, |
357 | login->rsp_length + padding) < 0) |
358 | goto err; |
359 | |
360 | login->rsp_length = 0; |
361 | |
362 | return 0; |
363 | |
364 | err: |
365 | if (login->login_complete) { |
366 | if (conn->rx_thread && conn->rx_thread_active) { |
367 | send_sig(SIGINT, conn->rx_thread, 1); |
368 | complete(&conn->rx_login_comp); |
369 | kthread_stop(k: conn->rx_thread); |
370 | } |
371 | if (conn->tx_thread && conn->tx_thread_active) { |
372 | send_sig(SIGINT, conn->tx_thread, 1); |
373 | kthread_stop(k: conn->tx_thread); |
374 | } |
375 | spin_lock(lock: &iscsit_global->ts_bitmap_lock); |
376 | bitmap_release_region(bitmap: iscsit_global->ts_bitmap, pos: conn->bitmap_id, |
377 | order: get_order(size: 1)); |
378 | spin_unlock(lock: &iscsit_global->ts_bitmap_lock); |
379 | } |
380 | return -1; |
381 | } |
382 | |
383 | static void iscsi_target_sk_data_ready(struct sock *sk) |
384 | { |
385 | struct iscsit_conn *conn = sk->sk_user_data; |
386 | bool rc; |
387 | |
388 | trace_sk_data_ready(sk); |
389 | pr_debug("Entering iscsi_target_sk_data_ready: conn: %p\n" , conn); |
390 | |
391 | write_lock_bh(&sk->sk_callback_lock); |
392 | if (!sk->sk_user_data) { |
393 | write_unlock_bh(&sk->sk_callback_lock); |
394 | return; |
395 | } |
396 | if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) { |
397 | write_unlock_bh(&sk->sk_callback_lock); |
398 | pr_debug("Got LOGIN_FLAGS_READY=0, conn: %p >>>>\n" , conn); |
399 | return; |
400 | } |
401 | if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { |
402 | write_unlock_bh(&sk->sk_callback_lock); |
403 | pr_debug("Got LOGIN_FLAGS_CLOSED=1, conn: %p >>>>\n" , conn); |
404 | return; |
405 | } |
406 | if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE, addr: &conn->login_flags)) { |
407 | write_unlock_bh(&sk->sk_callback_lock); |
408 | pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p >>>>\n" , conn); |
409 | if (iscsi_target_sk_data_ready == conn->orig_data_ready) |
410 | return; |
411 | conn->orig_data_ready(sk); |
412 | return; |
413 | } |
414 | |
415 | rc = schedule_delayed_work(dwork: &conn->login_work, delay: 0); |
416 | if (!rc) { |
417 | pr_debug("iscsi_target_sk_data_ready, schedule_delayed_work" |
418 | " got false\n" ); |
419 | } |
420 | write_unlock_bh(&sk->sk_callback_lock); |
421 | } |
422 | |
423 | static void iscsi_target_sk_state_change(struct sock *); |
424 | |
425 | static void iscsi_target_set_sock_callbacks(struct iscsit_conn *conn) |
426 | { |
427 | struct sock *sk; |
428 | |
429 | if (!conn->sock) |
430 | return; |
431 | |
432 | sk = conn->sock->sk; |
433 | pr_debug("Entering iscsi_target_set_sock_callbacks: conn: %p\n" , conn); |
434 | |
435 | write_lock_bh(&sk->sk_callback_lock); |
436 | sk->sk_user_data = conn; |
437 | conn->orig_data_ready = sk->sk_data_ready; |
438 | conn->orig_state_change = sk->sk_state_change; |
439 | sk->sk_data_ready = iscsi_target_sk_data_ready; |
440 | sk->sk_state_change = iscsi_target_sk_state_change; |
441 | write_unlock_bh(&sk->sk_callback_lock); |
442 | |
443 | sk->sk_sndtimeo = TA_LOGIN_TIMEOUT * HZ; |
444 | sk->sk_rcvtimeo = TA_LOGIN_TIMEOUT * HZ; |
445 | } |
446 | |
447 | static void iscsi_target_restore_sock_callbacks(struct iscsit_conn *conn) |
448 | { |
449 | struct sock *sk; |
450 | |
451 | if (!conn->sock) |
452 | return; |
453 | |
454 | sk = conn->sock->sk; |
455 | pr_debug("Entering iscsi_target_restore_sock_callbacks: conn: %p\n" , conn); |
456 | |
457 | write_lock_bh(&sk->sk_callback_lock); |
458 | if (!sk->sk_user_data) { |
459 | write_unlock_bh(&sk->sk_callback_lock); |
460 | return; |
461 | } |
462 | sk->sk_user_data = NULL; |
463 | sk->sk_data_ready = conn->orig_data_ready; |
464 | sk->sk_state_change = conn->orig_state_change; |
465 | write_unlock_bh(&sk->sk_callback_lock); |
466 | |
467 | sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; |
468 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; |
469 | } |
470 | |
471 | static int iscsi_target_do_login(struct iscsit_conn *, struct iscsi_login *); |
472 | |
473 | static bool __iscsi_target_sk_check_close(struct sock *sk) |
474 | { |
475 | if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) { |
476 | pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE," |
477 | "returning TRUE\n" ); |
478 | return true; |
479 | } |
480 | return false; |
481 | } |
482 | |
483 | static bool iscsi_target_sk_check_close(struct iscsit_conn *conn) |
484 | { |
485 | bool state = false; |
486 | |
487 | if (conn->sock) { |
488 | struct sock *sk = conn->sock->sk; |
489 | |
490 | read_lock_bh(&sk->sk_callback_lock); |
491 | state = (__iscsi_target_sk_check_close(sk) || |
492 | test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)); |
493 | read_unlock_bh(&sk->sk_callback_lock); |
494 | } |
495 | return state; |
496 | } |
497 | |
498 | static bool iscsi_target_sk_check_flag(struct iscsit_conn *conn, unsigned int flag) |
499 | { |
500 | bool state = false; |
501 | |
502 | if (conn->sock) { |
503 | struct sock *sk = conn->sock->sk; |
504 | |
505 | read_lock_bh(&sk->sk_callback_lock); |
506 | state = test_bit(flag, &conn->login_flags); |
507 | read_unlock_bh(&sk->sk_callback_lock); |
508 | } |
509 | return state; |
510 | } |
511 | |
512 | static bool iscsi_target_sk_check_and_clear(struct iscsit_conn *conn, unsigned int flag) |
513 | { |
514 | bool state = false; |
515 | |
516 | if (conn->sock) { |
517 | struct sock *sk = conn->sock->sk; |
518 | |
519 | write_lock_bh(&sk->sk_callback_lock); |
520 | state = (__iscsi_target_sk_check_close(sk) || |
521 | test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)); |
522 | if (!state) |
523 | clear_bit(nr: flag, addr: &conn->login_flags); |
524 | write_unlock_bh(&sk->sk_callback_lock); |
525 | } |
526 | return state; |
527 | } |
528 | |
529 | static void iscsi_target_login_drop(struct iscsit_conn *conn, struct iscsi_login *login) |
530 | { |
531 | bool zero_tsih = login->zero_tsih; |
532 | |
533 | iscsi_remove_failed_auth_entry(conn); |
534 | iscsi_target_nego_release(conn); |
535 | iscsi_target_login_sess_out(conn, zero_tsih, true); |
536 | } |
537 | |
538 | static void iscsi_target_do_login_rx(struct work_struct *work) |
539 | { |
540 | struct iscsit_conn *conn = container_of(work, |
541 | struct iscsit_conn, login_work.work); |
542 | struct iscsi_login *login = conn->login; |
543 | struct iscsi_np *np = login->np; |
544 | struct iscsi_portal_group *tpg = conn->tpg; |
545 | struct iscsi_tpg_np *tpg_np = conn->tpg_np; |
546 | int rc, zero_tsih = login->zero_tsih; |
547 | bool state; |
548 | |
549 | pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n" , |
550 | conn, current->comm, current->pid); |
551 | |
552 | spin_lock(lock: &conn->login_worker_lock); |
553 | set_bit(LOGIN_FLAGS_WORKER_RUNNING, addr: &conn->login_flags); |
554 | spin_unlock(lock: &conn->login_worker_lock); |
555 | /* |
556 | * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready() |
557 | * before initial PDU processing in iscsi_target_start_negotiation() |
558 | * has completed, go ahead and retry until it's cleared. |
559 | * |
560 | * Otherwise if the TCP connection drops while this is occuring, |
561 | * iscsi_target_start_negotiation() will detect the failure, call |
562 | * cancel_delayed_work_sync(&conn->login_work), and cleanup the |
563 | * remaining iscsi connection resources from iscsi_np process context. |
564 | */ |
565 | if (iscsi_target_sk_check_flag(conn, LOGIN_FLAGS_INITIAL_PDU)) { |
566 | schedule_delayed_work(dwork: &conn->login_work, delay: msecs_to_jiffies(m: 10)); |
567 | return; |
568 | } |
569 | |
570 | spin_lock(lock: &tpg->tpg_state_lock); |
571 | state = (tpg->tpg_state == TPG_STATE_ACTIVE); |
572 | spin_unlock(lock: &tpg->tpg_state_lock); |
573 | |
574 | if (!state) { |
575 | pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n" ); |
576 | goto err; |
577 | } |
578 | |
579 | if (iscsi_target_sk_check_close(conn)) { |
580 | pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n" ); |
581 | goto err; |
582 | } |
583 | |
584 | allow_signal(SIGINT); |
585 | rc = iscsit_set_login_timer_kworker(conn, current); |
586 | if (rc < 0) { |
587 | /* The login timer has already expired */ |
588 | pr_debug("iscsi_target_do_login_rx, login failed\n" ); |
589 | goto err; |
590 | } |
591 | |
592 | rc = conn->conn_transport->iscsit_get_login_rx(conn, login); |
593 | flush_signals(current); |
594 | |
595 | if (rc < 0) |
596 | goto err; |
597 | |
598 | pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n" , |
599 | conn, current->comm, current->pid); |
600 | |
601 | /* |
602 | * LOGIN_FLAGS_READ_ACTIVE is cleared so that sk_data_ready |
603 | * could be triggered again after this. |
604 | * |
605 | * LOGIN_FLAGS_WRITE_ACTIVE is cleared after we successfully |
606 | * process a login PDU, so that sk_state_chage can do login |
607 | * cleanup as needed if the socket is closed. If a delayed work is |
608 | * ongoing (LOGIN_FLAGS_WRITE_ACTIVE or LOGIN_FLAGS_READ_ACTIVE), |
609 | * sk_state_change will leave the cleanup to the delayed work or |
610 | * it will schedule a delayed work to do cleanup. |
611 | */ |
612 | if (conn->sock) { |
613 | struct sock *sk = conn->sock->sk; |
614 | |
615 | write_lock_bh(&sk->sk_callback_lock); |
616 | if (!test_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags)) { |
617 | clear_bit(LOGIN_FLAGS_READ_ACTIVE, addr: &conn->login_flags); |
618 | set_bit(LOGIN_FLAGS_WRITE_ACTIVE, addr: &conn->login_flags); |
619 | } |
620 | write_unlock_bh(&sk->sk_callback_lock); |
621 | } |
622 | |
623 | rc = iscsi_target_do_login(conn, login); |
624 | if (rc < 0) { |
625 | goto err; |
626 | } else if (!rc) { |
627 | if (iscsi_target_sk_check_and_clear(conn, |
628 | LOGIN_FLAGS_WRITE_ACTIVE)) |
629 | goto err; |
630 | |
631 | /* |
632 | * Set the login timer thread pointer to NULL to prevent the |
633 | * login process from getting stuck if the initiator |
634 | * stops sending data. |
635 | */ |
636 | rc = iscsit_set_login_timer_kworker(conn, NULL); |
637 | if (rc < 0) |
638 | goto err; |
639 | } else if (rc == 1) { |
640 | iscsit_stop_login_timer(conn); |
641 | cancel_delayed_work(dwork: &conn->login_work); |
642 | iscsi_target_nego_release(conn); |
643 | iscsi_post_login_handler(np, conn, zero_tsih); |
644 | iscsit_deaccess_np(np, tpg, tpg_np); |
645 | } |
646 | return; |
647 | |
648 | err: |
649 | iscsi_target_restore_sock_callbacks(conn); |
650 | iscsit_stop_login_timer(conn); |
651 | cancel_delayed_work(dwork: &conn->login_work); |
652 | iscsi_target_login_drop(conn, login); |
653 | iscsit_deaccess_np(np, tpg, tpg_np); |
654 | } |
655 | |
656 | static void iscsi_target_sk_state_change(struct sock *sk) |
657 | { |
658 | struct iscsit_conn *conn; |
659 | void (*orig_state_change)(struct sock *); |
660 | bool state; |
661 | |
662 | pr_debug("Entering iscsi_target_sk_state_change\n" ); |
663 | |
664 | write_lock_bh(&sk->sk_callback_lock); |
665 | conn = sk->sk_user_data; |
666 | if (!conn) { |
667 | write_unlock_bh(&sk->sk_callback_lock); |
668 | return; |
669 | } |
670 | orig_state_change = conn->orig_state_change; |
671 | |
672 | if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) { |
673 | pr_debug("Got LOGIN_FLAGS_READY=0 sk_state_change conn: %p\n" , |
674 | conn); |
675 | write_unlock_bh(&sk->sk_callback_lock); |
676 | orig_state_change(sk); |
677 | return; |
678 | } |
679 | state = __iscsi_target_sk_check_close(sk); |
680 | pr_debug("__iscsi_target_sk_close_change: state: %d\n" , state); |
681 | |
682 | if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags) || |
683 | test_bit(LOGIN_FLAGS_WRITE_ACTIVE, &conn->login_flags)) { |
684 | pr_debug("Got LOGIN_FLAGS_{READ|WRITE}_ACTIVE=1" |
685 | " sk_state_change conn: %p\n" , conn); |
686 | if (state) |
687 | set_bit(LOGIN_FLAGS_CLOSED, addr: &conn->login_flags); |
688 | write_unlock_bh(&sk->sk_callback_lock); |
689 | orig_state_change(sk); |
690 | return; |
691 | } |
692 | if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { |
693 | pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n" , |
694 | conn); |
695 | write_unlock_bh(&sk->sk_callback_lock); |
696 | orig_state_change(sk); |
697 | return; |
698 | } |
699 | /* |
700 | * If the TCP connection has dropped, go ahead and set LOGIN_FLAGS_CLOSED, |
701 | * but only queue conn->login_work -> iscsi_target_do_login_rx() |
702 | * processing if LOGIN_FLAGS_INITIAL_PDU has already been cleared. |
703 | * |
704 | * When iscsi_target_do_login_rx() runs, iscsi_target_sk_check_close() |
705 | * will detect the dropped TCP connection from delayed workqueue context. |
706 | * |
707 | * If LOGIN_FLAGS_INITIAL_PDU is still set, which means the initial |
708 | * iscsi_target_start_negotiation() is running, iscsi_target_do_login() |
709 | * via iscsi_target_sk_check_close() or iscsi_target_start_negotiation() |
710 | * via iscsi_target_sk_check_and_clear() is responsible for detecting the |
711 | * dropped TCP connection in iscsi_np process context, and cleaning up |
712 | * the remaining iscsi connection resources. |
713 | */ |
714 | if (state) { |
715 | pr_debug("iscsi_target_sk_state_change got failed state\n" ); |
716 | set_bit(LOGIN_FLAGS_CLOSED, addr: &conn->login_flags); |
717 | state = test_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags); |
718 | write_unlock_bh(&sk->sk_callback_lock); |
719 | |
720 | orig_state_change(sk); |
721 | |
722 | if (!state) |
723 | schedule_delayed_work(dwork: &conn->login_work, delay: 0); |
724 | return; |
725 | } |
726 | write_unlock_bh(&sk->sk_callback_lock); |
727 | |
728 | orig_state_change(sk); |
729 | } |
730 | |
731 | /* |
732 | * NOTE: We check for existing sessions or connections AFTER the initiator |
733 | * has been successfully authenticated in order to protect against faked |
734 | * ISID/TSIH combinations. |
735 | */ |
736 | static int iscsi_target_check_for_existing_instances( |
737 | struct iscsit_conn *conn, |
738 | struct iscsi_login *login) |
739 | { |
740 | if (login->checked_for_existing) |
741 | return 0; |
742 | |
743 | login->checked_for_existing = 1; |
744 | |
745 | if (!login->tsih) |
746 | return iscsi_check_for_session_reinstatement(conn); |
747 | else |
748 | return iscsi_login_post_auth_non_zero_tsih(conn, login->cid, |
749 | login->initial_exp_statsn); |
750 | } |
751 | |
752 | static int iscsi_target_do_authentication( |
753 | struct iscsit_conn *conn, |
754 | struct iscsi_login *login) |
755 | { |
756 | int authret; |
757 | u32 payload_length; |
758 | struct iscsi_param *param; |
759 | struct iscsi_login_req *login_req; |
760 | struct iscsi_login_rsp *login_rsp; |
761 | |
762 | login_req = (struct iscsi_login_req *) login->req; |
763 | login_rsp = (struct iscsi_login_rsp *) login->rsp; |
764 | payload_length = ntoh24(login_req->dlength); |
765 | |
766 | param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list); |
767 | if (!param) |
768 | return -1; |
769 | |
770 | authret = iscsi_handle_authentication( |
771 | conn, |
772 | in_buf: login->req_buf, |
773 | out_buf: login->rsp_buf, |
774 | in_length: payload_length, |
775 | out_length: &login->rsp_length, |
776 | authtype: param->value); |
777 | switch (authret) { |
778 | case 0: |
779 | pr_debug("Received OK response" |
780 | " from LIO Authentication, continuing.\n" ); |
781 | break; |
782 | case 1: |
783 | pr_debug("iSCSI security negotiation" |
784 | " completed successfully.\n" ); |
785 | login->auth_complete = 1; |
786 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) && |
787 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { |
788 | login_rsp->flags |= (ISCSI_FLAG_LOGIN_NEXT_STAGE1 | |
789 | ISCSI_FLAG_LOGIN_TRANSIT); |
790 | login->current_stage = 1; |
791 | } |
792 | return iscsi_target_check_for_existing_instances( |
793 | conn, login); |
794 | case 2: |
795 | pr_err("Security negotiation" |
796 | " failed.\n" ); |
797 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
798 | ISCSI_LOGIN_STATUS_AUTH_FAILED); |
799 | return -1; |
800 | default: |
801 | pr_err("Received unknown error %d from LIO" |
802 | " Authentication\n" , authret); |
803 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, |
804 | ISCSI_LOGIN_STATUS_TARGET_ERROR); |
805 | return -1; |
806 | } |
807 | |
808 | return 0; |
809 | } |
810 | |
811 | bool iscsi_conn_auth_required(struct iscsit_conn *conn) |
812 | { |
813 | struct iscsi_node_acl *nacl; |
814 | struct se_node_acl *se_nacl; |
815 | |
816 | if (conn->sess->sess_ops->SessionType) { |
817 | /* |
818 | * For SessionType=Discovery |
819 | */ |
820 | return conn->tpg->tpg_attrib.authentication; |
821 | } |
822 | /* |
823 | * For SessionType=Normal |
824 | */ |
825 | se_nacl = conn->sess->se_sess->se_node_acl; |
826 | if (!se_nacl) { |
827 | pr_debug("Unknown ACL is trying to connect\n" ); |
828 | return true; |
829 | } |
830 | |
831 | if (se_nacl->dynamic_node_acl) { |
832 | pr_debug("Dynamic ACL %s is trying to connect\n" , |
833 | se_nacl->initiatorname); |
834 | return conn->tpg->tpg_attrib.authentication; |
835 | } |
836 | |
837 | pr_debug("Known ACL %s is trying to connect\n" , |
838 | se_nacl->initiatorname); |
839 | |
840 | nacl = to_iscsi_nacl(se_nacl); |
841 | if (nacl->node_attrib.authentication == NA_AUTHENTICATION_INHERITED) |
842 | return conn->tpg->tpg_attrib.authentication; |
843 | |
844 | return nacl->node_attrib.authentication; |
845 | } |
846 | |
847 | static int iscsi_target_handle_csg_zero( |
848 | struct iscsit_conn *conn, |
849 | struct iscsi_login *login) |
850 | { |
851 | int ret; |
852 | u32 payload_length; |
853 | struct iscsi_param *param; |
854 | struct iscsi_login_req *login_req; |
855 | struct iscsi_login_rsp *login_rsp; |
856 | |
857 | login_req = (struct iscsi_login_req *) login->req; |
858 | login_rsp = (struct iscsi_login_rsp *) login->rsp; |
859 | payload_length = ntoh24(login_req->dlength); |
860 | |
861 | param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list); |
862 | if (!param) |
863 | return -1; |
864 | |
865 | ret = iscsi_decode_text_input( |
866 | PHASE_SECURITY|PHASE_DECLARATIVE, |
867 | SENDER_INITIATOR|SENDER_RECEIVER, |
868 | login->req_buf, |
869 | payload_length, |
870 | conn); |
871 | if (ret < 0) |
872 | return -1; |
873 | |
874 | if (ret > 0) { |
875 | if (login->auth_complete) { |
876 | pr_err("Initiator has already been" |
877 | " successfully authenticated, but is still" |
878 | " sending %s keys.\n" , param->value); |
879 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
880 | ISCSI_LOGIN_STATUS_INIT_ERR); |
881 | return -1; |
882 | } |
883 | |
884 | goto do_auth; |
885 | } else if (!payload_length) { |
886 | pr_err("Initiator sent zero length security payload," |
887 | " login failed\n" ); |
888 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
889 | ISCSI_LOGIN_STATUS_AUTH_FAILED); |
890 | return -1; |
891 | } |
892 | |
893 | if (login->first_request) |
894 | if (iscsi_target_check_first_request(conn, login) < 0) |
895 | return -1; |
896 | |
897 | ret = iscsi_encode_text_output( |
898 | PHASE_SECURITY|PHASE_DECLARATIVE, |
899 | SENDER_TARGET, |
900 | login->rsp_buf, |
901 | &login->rsp_length, |
902 | conn->param_list, |
903 | conn->tpg->tpg_attrib.login_keys_workaround); |
904 | if (ret < 0) |
905 | return -1; |
906 | |
907 | if (!iscsi_check_negotiated_keys(conn->param_list)) { |
908 | bool auth_required = iscsi_conn_auth_required(conn); |
909 | |
910 | if (auth_required) { |
911 | if (!strncmp(param->value, NONE, 4)) { |
912 | pr_err("Initiator sent AuthMethod=None but" |
913 | " Target is enforcing iSCSI Authentication," |
914 | " login failed.\n" ); |
915 | iscsit_tx_login_rsp(conn, |
916 | ISCSI_STATUS_CLS_INITIATOR_ERR, |
917 | ISCSI_LOGIN_STATUS_AUTH_FAILED); |
918 | return -1; |
919 | } |
920 | |
921 | if (!login->auth_complete) |
922 | return 0; |
923 | |
924 | if (strncmp(param->value, NONE, 4) && |
925 | !login->auth_complete) |
926 | return 0; |
927 | } |
928 | |
929 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) && |
930 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { |
931 | login_rsp->flags |= ISCSI_FLAG_LOGIN_NEXT_STAGE1 | |
932 | ISCSI_FLAG_LOGIN_TRANSIT; |
933 | login->current_stage = 1; |
934 | } |
935 | } |
936 | |
937 | return 0; |
938 | do_auth: |
939 | return iscsi_target_do_authentication(conn, login); |
940 | } |
941 | |
942 | static bool iscsi_conn_authenticated(struct iscsit_conn *conn, |
943 | struct iscsi_login *login) |
944 | { |
945 | if (!iscsi_conn_auth_required(conn)) |
946 | return true; |
947 | |
948 | if (login->auth_complete) |
949 | return true; |
950 | |
951 | return false; |
952 | } |
953 | |
954 | static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_login *login) |
955 | { |
956 | int ret; |
957 | u32 payload_length; |
958 | struct iscsi_login_req *login_req; |
959 | struct iscsi_login_rsp *login_rsp; |
960 | |
961 | login_req = (struct iscsi_login_req *) login->req; |
962 | login_rsp = (struct iscsi_login_rsp *) login->rsp; |
963 | payload_length = ntoh24(login_req->dlength); |
964 | |
965 | ret = iscsi_decode_text_input( |
966 | PHASE_OPERATIONAL|PHASE_DECLARATIVE, |
967 | SENDER_INITIATOR|SENDER_RECEIVER, |
968 | login->req_buf, |
969 | payload_length, |
970 | conn); |
971 | if (ret < 0) { |
972 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
973 | ISCSI_LOGIN_STATUS_INIT_ERR); |
974 | return -1; |
975 | } |
976 | |
977 | if (login->first_request) |
978 | if (iscsi_target_check_first_request(conn, login) < 0) |
979 | return -1; |
980 | |
981 | if (iscsi_target_check_for_existing_instances(conn, login) < 0) |
982 | return -1; |
983 | |
984 | ret = iscsi_encode_text_output( |
985 | PHASE_OPERATIONAL|PHASE_DECLARATIVE, |
986 | SENDER_TARGET, |
987 | login->rsp_buf, |
988 | &login->rsp_length, |
989 | conn->param_list, |
990 | conn->tpg->tpg_attrib.login_keys_workaround); |
991 | if (ret < 0) { |
992 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
993 | ISCSI_LOGIN_STATUS_INIT_ERR); |
994 | return -1; |
995 | } |
996 | |
997 | if (!iscsi_conn_authenticated(conn, login)) { |
998 | pr_err("Initiator is requesting CSG: 1, has not been" |
999 | " successfully authenticated, and the Target is" |
1000 | " enforcing iSCSI Authentication, login failed.\n" ); |
1001 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
1002 | ISCSI_LOGIN_STATUS_AUTH_FAILED); |
1003 | return -1; |
1004 | } |
1005 | |
1006 | if (!iscsi_check_negotiated_keys(conn->param_list)) |
1007 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE3) && |
1008 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) |
1009 | login_rsp->flags |= ISCSI_FLAG_LOGIN_NEXT_STAGE3 | |
1010 | ISCSI_FLAG_LOGIN_TRANSIT; |
1011 | |
1012 | return 0; |
1013 | } |
1014 | |
1015 | /* |
1016 | * RETURN VALUE: |
1017 | * |
1018 | * 1 = Login successful |
1019 | * -1 = Login failed |
1020 | * 0 = More PDU exchanges required |
1021 | */ |
1022 | static int iscsi_target_do_login(struct iscsit_conn *conn, struct iscsi_login *login) |
1023 | { |
1024 | int pdu_count = 0; |
1025 | struct iscsi_login_req *login_req; |
1026 | struct iscsi_login_rsp *login_rsp; |
1027 | |
1028 | login_req = (struct iscsi_login_req *) login->req; |
1029 | login_rsp = (struct iscsi_login_rsp *) login->rsp; |
1030 | |
1031 | while (1) { |
1032 | if (++pdu_count > MAX_LOGIN_PDUS) { |
1033 | pr_err("MAX_LOGIN_PDUS count reached.\n" ); |
1034 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, |
1035 | ISCSI_LOGIN_STATUS_TARGET_ERROR); |
1036 | return -1; |
1037 | } |
1038 | |
1039 | switch (ISCSI_LOGIN_CURRENT_STAGE(login_req->flags)) { |
1040 | case 0: |
1041 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK; |
1042 | if (iscsi_target_handle_csg_zero(conn, login) < 0) |
1043 | return -1; |
1044 | break; |
1045 | case 1: |
1046 | login_rsp->flags |= ISCSI_FLAG_LOGIN_CURRENT_STAGE1; |
1047 | if (iscsi_target_handle_csg_one(conn, login) < 0) |
1048 | return -1; |
1049 | if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { |
1050 | /* |
1051 | * Check to make sure the TCP connection has not |
1052 | * dropped asynchronously while session reinstatement |
1053 | * was occuring in this kthread context, before |
1054 | * transitioning to full feature phase operation. |
1055 | */ |
1056 | if (iscsi_target_sk_check_close(conn)) |
1057 | return -1; |
1058 | |
1059 | login->tsih = conn->sess->tsih; |
1060 | login->login_complete = 1; |
1061 | iscsi_target_restore_sock_callbacks(conn); |
1062 | if (iscsi_target_do_tx_login_io(conn, |
1063 | login) < 0) |
1064 | return -1; |
1065 | return 1; |
1066 | } |
1067 | break; |
1068 | default: |
1069 | pr_err("Illegal CSG: %d received from" |
1070 | " Initiator, protocol error.\n" , |
1071 | ISCSI_LOGIN_CURRENT_STAGE(login_req->flags)); |
1072 | break; |
1073 | } |
1074 | |
1075 | if (iscsi_target_do_tx_login_io(conn, login) < 0) |
1076 | return -1; |
1077 | |
1078 | if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { |
1079 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_TRANSIT; |
1080 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; |
1081 | } |
1082 | break; |
1083 | } |
1084 | |
1085 | return 0; |
1086 | } |
1087 | |
1088 | static void iscsi_initiatorname_tolower( |
1089 | char *param_buf) |
1090 | { |
1091 | char *c; |
1092 | u32 iqn_size = strlen(param_buf), i; |
1093 | |
1094 | for (i = 0; i < iqn_size; i++) { |
1095 | c = ¶m_buf[i]; |
1096 | if (!isupper(*c)) |
1097 | continue; |
1098 | |
1099 | *c = tolower(*c); |
1100 | } |
1101 | } |
1102 | |
1103 | /* |
1104 | * Processes the first Login Request.. |
1105 | */ |
1106 | int iscsi_target_locate_portal( |
1107 | struct iscsi_np *np, |
1108 | struct iscsit_conn *conn, |
1109 | struct iscsi_login *login) |
1110 | { |
1111 | char *i_buf = NULL, *s_buf = NULL, *t_buf = NULL; |
1112 | char *tmpbuf, *start = NULL, *end = NULL, *key, *value; |
1113 | struct iscsit_session *sess = conn->sess; |
1114 | struct iscsi_tiqn *tiqn; |
1115 | struct iscsi_tpg_np *tpg_np = NULL; |
1116 | struct iscsi_login_req *login_req; |
1117 | struct se_node_acl *se_nacl; |
1118 | u32 payload_length, queue_depth = 0; |
1119 | int sessiontype = 0, ret = 0, tag_num, tag_size; |
1120 | |
1121 | INIT_DELAYED_WORK(&conn->login_work, iscsi_target_do_login_rx); |
1122 | iscsi_target_set_sock_callbacks(conn); |
1123 | |
1124 | login->np = np; |
1125 | conn->tpg = NULL; |
1126 | |
1127 | login_req = (struct iscsi_login_req *) login->req; |
1128 | payload_length = ntoh24(login_req->dlength); |
1129 | |
1130 | tmpbuf = kmemdup_nul(s: login->req_buf, len: payload_length, GFP_KERNEL); |
1131 | if (!tmpbuf) { |
1132 | pr_err("Unable to allocate memory for tmpbuf.\n" ); |
1133 | return -1; |
1134 | } |
1135 | |
1136 | start = tmpbuf; |
1137 | end = (start + payload_length); |
1138 | |
1139 | /* |
1140 | * Locate the initial keys expected from the Initiator node in |
1141 | * the first login request in order to progress with the login phase. |
1142 | */ |
1143 | while (start < end) { |
1144 | if (iscsi_extract_key_value(start, &key, &value) < 0) { |
1145 | ret = -1; |
1146 | goto out; |
1147 | } |
1148 | |
1149 | if (!strncmp(key, "InitiatorName" , 13)) |
1150 | i_buf = value; |
1151 | else if (!strncmp(key, "SessionType" , 11)) |
1152 | s_buf = value; |
1153 | else if (!strncmp(key, "TargetName" , 10)) |
1154 | t_buf = value; |
1155 | |
1156 | start += strlen(key) + strlen(value) + 2; |
1157 | } |
1158 | /* |
1159 | * See 5.3. Login Phase. |
1160 | */ |
1161 | if (!i_buf) { |
1162 | pr_err("InitiatorName key not received" |
1163 | " in first login request.\n" ); |
1164 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
1165 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); |
1166 | ret = -1; |
1167 | goto out; |
1168 | } |
1169 | /* |
1170 | * Convert the incoming InitiatorName to lowercase following |
1171 | * RFC-3720 3.2.6.1. section c) that says that iSCSI IQNs |
1172 | * are NOT case sensitive. |
1173 | */ |
1174 | iscsi_initiatorname_tolower(param_buf: i_buf); |
1175 | |
1176 | if (!s_buf) { |
1177 | if (!login->leading_connection) |
1178 | goto get_target; |
1179 | |
1180 | pr_err("SessionType key not received" |
1181 | " in first login request.\n" ); |
1182 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
1183 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); |
1184 | ret = -1; |
1185 | goto out; |
1186 | } |
1187 | |
1188 | /* |
1189 | * Use default portal group for discovery sessions. |
1190 | */ |
1191 | sessiontype = strncmp(s_buf, DISCOVERY, 9); |
1192 | if (!sessiontype) { |
1193 | if (!login->leading_connection) |
1194 | goto get_target; |
1195 | |
1196 | sess->sess_ops->SessionType = 1; |
1197 | /* |
1198 | * Setup crc32c modules from libcrypto |
1199 | */ |
1200 | if (iscsi_login_setup_crypto(conn) < 0) { |
1201 | pr_err("iscsi_login_setup_crypto() failed\n" ); |
1202 | ret = -1; |
1203 | goto out; |
1204 | } |
1205 | /* |
1206 | * Serialize access across the discovery struct iscsi_portal_group to |
1207 | * process login attempt. |
1208 | */ |
1209 | conn->tpg = iscsit_global->discovery_tpg; |
1210 | if (iscsit_access_np(np, conn->tpg) < 0) { |
1211 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, |
1212 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); |
1213 | conn->tpg = NULL; |
1214 | ret = -1; |
1215 | goto out; |
1216 | } |
1217 | ret = 0; |
1218 | goto alloc_tags; |
1219 | } |
1220 | |
1221 | get_target: |
1222 | if (!t_buf) { |
1223 | pr_err("TargetName key not received" |
1224 | " in first login request while" |
1225 | " SessionType=Normal.\n" ); |
1226 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
1227 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); |
1228 | ret = -1; |
1229 | goto out; |
1230 | } |
1231 | |
1232 | /* |
1233 | * Locate Target IQN from Storage Node. |
1234 | */ |
1235 | tiqn = iscsit_get_tiqn_for_login(t_buf); |
1236 | if (!tiqn) { |
1237 | pr_err("Unable to locate Target IQN: %s in" |
1238 | " Storage Node\n" , t_buf); |
1239 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, |
1240 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); |
1241 | ret = -1; |
1242 | goto out; |
1243 | } |
1244 | pr_debug("Located Storage Object: %s\n" , tiqn->tiqn); |
1245 | |
1246 | /* |
1247 | * Locate Target Portal Group from Storage Node. |
1248 | */ |
1249 | conn->tpg = iscsit_get_tpg_from_np(tiqn, np, &tpg_np); |
1250 | if (!conn->tpg) { |
1251 | pr_err("Unable to locate Target Portal Group" |
1252 | " on %s\n" , tiqn->tiqn); |
1253 | iscsit_put_tiqn_for_login(tiqn); |
1254 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, |
1255 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); |
1256 | ret = -1; |
1257 | goto out; |
1258 | } |
1259 | conn->tpg_np = tpg_np; |
1260 | pr_debug("Located Portal Group Object: %hu\n" , conn->tpg->tpgt); |
1261 | /* |
1262 | * Setup crc32c modules from libcrypto |
1263 | */ |
1264 | if (iscsi_login_setup_crypto(conn) < 0) { |
1265 | pr_err("iscsi_login_setup_crypto() failed\n" ); |
1266 | kref_put(kref: &tpg_np->tpg_np_kref, release: iscsit_login_kref_put); |
1267 | iscsit_put_tiqn_for_login(tiqn); |
1268 | conn->tpg = NULL; |
1269 | ret = -1; |
1270 | goto out; |
1271 | } |
1272 | /* |
1273 | * Serialize access across the struct iscsi_portal_group to |
1274 | * process login attempt. |
1275 | */ |
1276 | if (iscsit_access_np(np, conn->tpg) < 0) { |
1277 | kref_put(kref: &tpg_np->tpg_np_kref, release: iscsit_login_kref_put); |
1278 | iscsit_put_tiqn_for_login(tiqn); |
1279 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, |
1280 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); |
1281 | conn->tpg = NULL; |
1282 | ret = -1; |
1283 | goto out; |
1284 | } |
1285 | |
1286 | /* |
1287 | * conn->sess->node_acl will be set when the referenced |
1288 | * struct iscsit_session is located from received ISID+TSIH in |
1289 | * iscsi_login_non_zero_tsih_s2(). |
1290 | */ |
1291 | if (!login->leading_connection) { |
1292 | ret = 0; |
1293 | goto out; |
1294 | } |
1295 | |
1296 | /* |
1297 | * This value is required in iscsi_login_zero_tsih_s2() |
1298 | */ |
1299 | sess->sess_ops->SessionType = 0; |
1300 | |
1301 | /* |
1302 | * Locate incoming Initiator IQN reference from Storage Node. |
1303 | */ |
1304 | sess->se_sess->se_node_acl = core_tpg_check_initiator_node_acl( |
1305 | &conn->tpg->tpg_se_tpg, i_buf); |
1306 | if (!sess->se_sess->se_node_acl) { |
1307 | pr_err("iSCSI Initiator Node: %s is not authorized to" |
1308 | " access iSCSI target portal group: %hu.\n" , |
1309 | i_buf, conn->tpg->tpgt); |
1310 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, |
1311 | ISCSI_LOGIN_STATUS_TGT_FORBIDDEN); |
1312 | ret = -1; |
1313 | goto out; |
1314 | } |
1315 | se_nacl = sess->se_sess->se_node_acl; |
1316 | queue_depth = se_nacl->queue_depth; |
1317 | /* |
1318 | * Setup pre-allocated tags based upon allowed per NodeACL CmdSN |
1319 | * depth for non immediate commands, plus extra tags for immediate |
1320 | * commands. |
1321 | * |
1322 | * Also enforce a ISCSIT_MIN_TAGS to prevent unnecessary contention |
1323 | * in per-cpu-ida tag allocation logic + small queue_depth. |
1324 | */ |
1325 | alloc_tags: |
1326 | tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth); |
1327 | tag_num = (tag_num * 2) + ISCSIT_EXTRA_TAGS; |
1328 | tag_size = sizeof(struct iscsit_cmd) + conn->conn_transport->priv_size; |
1329 | |
1330 | ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size); |
1331 | if (ret < 0) { |
1332 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, |
1333 | ISCSI_LOGIN_STATUS_NO_RESOURCES); |
1334 | ret = -1; |
1335 | } |
1336 | out: |
1337 | kfree(objp: tmpbuf); |
1338 | return ret; |
1339 | } |
1340 | |
1341 | int iscsi_target_start_negotiation( |
1342 | struct iscsi_login *login, |
1343 | struct iscsit_conn *conn) |
1344 | { |
1345 | int ret; |
1346 | |
1347 | if (conn->sock) { |
1348 | struct sock *sk = conn->sock->sk; |
1349 | |
1350 | write_lock_bh(&sk->sk_callback_lock); |
1351 | set_bit(LOGIN_FLAGS_READY, addr: &conn->login_flags); |
1352 | set_bit(LOGIN_FLAGS_INITIAL_PDU, addr: &conn->login_flags); |
1353 | write_unlock_bh(&sk->sk_callback_lock); |
1354 | } |
1355 | /* |
1356 | * If iscsi_target_do_login returns zero to signal more PDU |
1357 | * exchanges are required to complete the login, go ahead and |
1358 | * clear LOGIN_FLAGS_INITIAL_PDU but only if the TCP connection |
1359 | * is still active. |
1360 | * |
1361 | * Otherwise if TCP connection dropped asynchronously, go ahead |
1362 | * and perform connection cleanup now. |
1363 | */ |
1364 | ret = iscsi_target_do_login(conn, login); |
1365 | if (!ret) { |
1366 | spin_lock(lock: &conn->login_worker_lock); |
1367 | |
1368 | if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU)) |
1369 | ret = -1; |
1370 | else if (!test_bit(LOGIN_FLAGS_WORKER_RUNNING, &conn->login_flags)) { |
1371 | if (iscsit_set_login_timer_kworker(conn, NULL) < 0) { |
1372 | /* |
1373 | * The timeout has expired already. |
1374 | * Schedule login_work to perform the cleanup. |
1375 | */ |
1376 | schedule_delayed_work(dwork: &conn->login_work, delay: 0); |
1377 | } |
1378 | } |
1379 | |
1380 | spin_unlock(lock: &conn->login_worker_lock); |
1381 | } |
1382 | |
1383 | if (ret < 0) { |
1384 | iscsi_target_restore_sock_callbacks(conn); |
1385 | iscsi_remove_failed_auth_entry(conn); |
1386 | } |
1387 | if (ret != 0) { |
1388 | iscsit_stop_login_timer(conn); |
1389 | cancel_delayed_work_sync(dwork: &conn->login_work); |
1390 | iscsi_target_nego_release(conn); |
1391 | } |
1392 | |
1393 | return ret; |
1394 | } |
1395 | |
1396 | void iscsi_target_nego_release(struct iscsit_conn *conn) |
1397 | { |
1398 | struct iscsi_login *login = conn->conn_login; |
1399 | |
1400 | if (!login) |
1401 | return; |
1402 | |
1403 | kfree(objp: login->req_buf); |
1404 | kfree(objp: login->rsp_buf); |
1405 | kfree(objp: login); |
1406 | |
1407 | conn->conn_login = NULL; |
1408 | } |
1409 | |