29 #include <sys/conf.h>
30 #include <sys/file.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/modctl.h>
34 #include <sys/scsi/generic/persist.h>
35 #include <sys/scsi/scsi_names.h>
36
37 #include <sys/socket.h>
38 #include <sys/strsubr.h>
39 #include <sys/sysmacros.h>
40 #include <sys/note.h>
41 #include <sys/sdt.h>
42 #include <sys/errno.h>
43
44 #include <sys/stmf.h>
45 #include <sys/stmf_ioctl.h>
46 #include <sys/portif.h>
47 #include <sys/idm/idm.h>
48 #include <sys/idm/idm_text.h>
49
50 #define ISCSIT_LOGIN_SM_STRINGS
51 #include "iscsit.h"
52 #include "iscsit_auth.h"
53
54 typedef struct {
55 list_node_t le_ctx_node;
56 iscsit_login_event_t le_ctx_event;
57 idm_pdu_t *le_pdu;
58 } login_event_ctx_t;
59
60 #ifndef TRUE
61 #define TRUE B_TRUE
62 #endif
63
64 #ifndef FALSE
65 #define FALSE B_FALSE
66 #endif
67
68 #define DEFAULT_RADIUS_PORT 1812
715
716 new_state = (new_state < ILS_MAX_STATE) ?
717 new_state : ILS_UNDEFINED;
718
719 IDM_SM_LOG(CE_NOTE, "login_sm_new_state: conn %p "
720 "%s (%d) --> %s (%d)\n", (void *)ict->ict_ic,
721 iscsit_ils_name[lsm->icl_login_state], lsm->icl_login_state,
722 iscsit_ils_name[new_state], new_state);
723
724 DTRACE_PROBE3(login__state__change,
725 iscsit_conn_t *, ict, login_event_ctx_t *, ctx,
726 iscsit_login_state_t, new_state);
727
728 mutex_enter(&lsm->icl_mutex);
729 idm_sm_audit_state_change(&lsm->icl_state_audit, SAS_ISCSIT_LOGIN,
730 (int)lsm->icl_login_state, (int)new_state);
731 lsm->icl_login_last_state = lsm->icl_login_state;
732 lsm->icl_login_state = new_state;
733 mutex_exit(&lsm->icl_mutex);
734
735 switch (lsm->icl_login_state) {
736 case ILS_LOGIN_WAITING:
737 /* Do nothing, waiting for more login PDU's */
738 break;
739 case ILS_LOGIN_PROCESSING:
740 /* All login PDU's received, process login request */
741 login_sm_process_request(ict);
742 break;
743 case ILS_LOGIN_RESPONDING:
744 rpdu = login_sm_build_login_response(ict);
745 login_sm_send_next_response(ict, rpdu);
746 break;
747 case ILS_LOGIN_RESPONDED:
748 /* clean up the login response idm text buffer */
749 if (lsm->icl_login_resp_itb != NULL) {
750 idm_itextbuf_free(lsm->icl_login_resp_itb);
751 lsm->icl_login_resp_itb = NULL;
752 }
753 break;
754 case ILS_LOGIN_FFP:
755 login_sm_ffp_actions(ict);
1731 } else if ((strcmp(auth, PA_AUTH_CHAP) == 0) &&
1732 (lsm->icl_auth.ca_ini_chapsecretlen == 0)) {
1733 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1734 ISCSI_LOGIN_STATUS_AUTH_FAILED);
1735 idmrc = IDM_STATUS_FAIL;
1736 }
1737
1738 ISCSIT_GLOBAL_UNLOCK();
1739
1740 return (idmrc);
1741 }
1742
1743
1744 static idm_status_t
1745 login_sm_session_register(iscsit_conn_t *ict)
1746 {
1747 iscsit_sess_t *ist = ict->ict_sess;
1748 stmf_scsi_session_t *ss;
1749 iscsi_transport_id_t *iscsi_tptid;
1750 uint16_t ident_len, adn_len, tptid_sz;
1751
1752 /*
1753 * Hold target mutex until we have finished registering with STMF
1754 */
1755 mutex_enter(&ist->ist_tgt->target_mutex);
1756 if (ist->ist_tgt->target_state != TS_STMF_ONLINE) {
1757 mutex_exit(&ist->ist_tgt->target_mutex);
1758 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1759 ISCSI_LOGIN_STATUS_TGT_REMOVED);
1760 return (IDM_STATUS_FAIL);
1761 }
1762
1763 ss = stmf_alloc(STMF_STRUCT_SCSI_SESSION, 0,
1764 0);
1765 if (ss == NULL) {
1766 mutex_exit(&ist->ist_tgt->target_mutex);
1767 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1768 ISCSI_LOGIN_STATUS_NO_RESOURCES);
1769 return (IDM_STATUS_FAIL);
1770 }
1791 ist->ist_initiator_name, ident_len);
1792
1793 ss->ss_lport = ist->ist_lport;
1794
1795 if (stmf_register_scsi_session(ict->ict_sess->ist_lport, ss) !=
1796 STMF_SUCCESS) {
1797 mutex_exit(&ist->ist_tgt->target_mutex);
1798 kmem_free(ss->ss_rport_id,
1799 sizeof (scsi_devid_desc_t) +
1800 strlen(ist->ist_initiator_name) + 1);
1801 stmf_remote_port_free(ss->ss_rport);
1802 stmf_free(ss);
1803 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1804 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1805 return (IDM_STATUS_FAIL);
1806 }
1807
1808 ss->ss_port_private = ict->ict_sess;
1809 ict->ict_sess->ist_stmf_sess = ss;
1810 mutex_exit(&ist->ist_tgt->target_mutex);
1811
1812 return (IDM_STATUS_SUCCESS);
1813 }
1814
1815
1816 static idm_status_t
1817 login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu)
1818 {
1819 uint8_t csg_req;
1820 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1821 iscsi_login_hdr_t *lh = (iscsi_login_hdr_t *)pdu->isp_hdr;
1822 iscsi_login_rsp_hdr_t *lh_resp = lsm->icl_login_resp_tmpl;
1823
1824 /*
1825 * Check CSG
1826 */
1827 csg_req = ISCSI_LOGIN_CURRENT_STAGE(lh->flags);
1828 switch (csg_req) {
1829 case ISCSI_SECURITY_NEGOTIATION_STAGE:
1830 case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
2709 idm_status = IDM_STATUS_FAIL;
2710 }
2711 return (idm_status);
2712 }
2713
2714 static char *
2715 iscsit_fold_name(char *name, size_t *buflen)
2716 {
2717 char *ret;
2718 const char *sns;
2719 int errnum;
2720 int flag = U8_TEXTPREP_NFKC;
2721 size_t inlen, outlen, coff;
2722
2723 if (name == NULL)
2724 return (NULL);
2725
2726 /* Check for one of the supported name types */
2727 if (strncasecmp(name, SNS_EUI ".", strlen(SNS_EUI) + 1) == 0) {
2728 sns = SNS_EUI;
2729 *buflen = SNS_EUI_U8_LEN_MAX + 1;
2730 flag |= U8_TEXTPREP_TOUPPER;
2731 } else if (strncasecmp(name, SNS_IQN ".", strlen(SNS_IQN) + 1) == 0) {
2732 sns = SNS_IQN;
2733 *buflen = SNS_IQN_U8_LEN_MAX + 1;
2734 flag |= U8_TEXTPREP_TOLOWER;
2735 } else if (strncasecmp(name, SNS_NAA ".", strlen(SNS_NAA) + 1) == 0) {
2736 sns = SNS_NAA;
2737 *buflen = SNS_NAA_U8_LEN_MAX + 1;
2738 flag |= U8_TEXTPREP_TOUPPER;
2739 } else {
2740 return (NULL);
2741 }
2742
2743 ret = kmem_zalloc(*buflen, KM_SLEEP);
2744 coff = strlen(sns);
2745 inlen = strlen(name) - coff;
2746 outlen = *buflen - coff;
2747
2748 /* Fold the case and normalize string */
2749 if (u8_textprep_str(name + coff, &inlen, ret + coff, &outlen, flag,
2750 U8_UNICODE_320, &errnum) == (size_t)-1) {
2751 kmem_free(ret, *buflen);
2752 return (NULL);
2753 }
2754
2755 /* Copy the name type prefix */
2756 bcopy(sns, ret, coff);
2757
2758 return (ret);
2759 }
|
29 #include <sys/conf.h>
30 #include <sys/file.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/modctl.h>
34 #include <sys/scsi/generic/persist.h>
35 #include <sys/scsi/scsi_names.h>
36
37 #include <sys/socket.h>
38 #include <sys/strsubr.h>
39 #include <sys/sysmacros.h>
40 #include <sys/note.h>
41 #include <sys/sdt.h>
42 #include <sys/errno.h>
43
44 #include <sys/stmf.h>
45 #include <sys/stmf_ioctl.h>
46 #include <sys/portif.h>
47 #include <sys/idm/idm.h>
48 #include <sys/idm/idm_text.h>
49 #include <sys/idm/idm_so.h>
50
51 #define ISCSIT_LOGIN_SM_STRINGS
52 #include "iscsit.h"
53 #include "iscsit_auth.h"
54
55 typedef struct {
56 list_node_t le_ctx_node;
57 iscsit_login_event_t le_ctx_event;
58 idm_pdu_t *le_pdu;
59 } login_event_ctx_t;
60
61 #ifndef TRUE
62 #define TRUE B_TRUE
63 #endif
64
65 #ifndef FALSE
66 #define FALSE B_FALSE
67 #endif
68
69 #define DEFAULT_RADIUS_PORT 1812
716
717 new_state = (new_state < ILS_MAX_STATE) ?
718 new_state : ILS_UNDEFINED;
719
720 IDM_SM_LOG(CE_NOTE, "login_sm_new_state: conn %p "
721 "%s (%d) --> %s (%d)\n", (void *)ict->ict_ic,
722 iscsit_ils_name[lsm->icl_login_state], lsm->icl_login_state,
723 iscsit_ils_name[new_state], new_state);
724
725 DTRACE_PROBE3(login__state__change,
726 iscsit_conn_t *, ict, login_event_ctx_t *, ctx,
727 iscsit_login_state_t, new_state);
728
729 mutex_enter(&lsm->icl_mutex);
730 idm_sm_audit_state_change(&lsm->icl_state_audit, SAS_ISCSIT_LOGIN,
731 (int)lsm->icl_login_state, (int)new_state);
732 lsm->icl_login_last_state = lsm->icl_login_state;
733 lsm->icl_login_state = new_state;
734 mutex_exit(&lsm->icl_mutex);
735
736 /*
737 * Tale of caution here. The use of new_state instead of using
738 * lsm->icl_login_state is deliberate (which had been used originally).
739 * Since the icl_mutex is dropped under the right circumstances
740 * the login state changes between setting the state and examining
741 * the state to proceed. No big surprise since the lock was being
742 * used in the first place to prevent just that type of change.
743 *
744 * There has been a case where network errors occurred while a client
745 * was attempting to reinstate the connection causing multiple
746 * login packets to arrive into the state machine. Those multiple
747 * packets which were processed incorrectly caused the reference
748 * count on the connection to be one higher than it should be and
749 * from then on the connection can't close correctly causing a hang.
750 *
751 * Upon examination of the core it was found that the connection
752 * audit data had calls looking like:
753 * login_sm_event_dispatch
754 * login_sm_processing
755 * login_sm_new_state
756 * That call sequence means the new state was/is ILS_LOGIN_ERROR
757 * yet the audit trail continues with a call to
758 * login_sm_send_next_response
759 * which could only occur if icl_login_state had changed. Had the
760 * design of COMSTAR taken this into account the code would
761 * originally have held the icl_mutex across the processing of the
762 * state processing. Lock order and calls which sleep prevent that
763 * from being possible. The next best solution is to use the local
764 * variable which holds the state.
765 */
766 switch (new_state) {
767 case ILS_LOGIN_WAITING:
768 /* Do nothing, waiting for more login PDU's */
769 break;
770 case ILS_LOGIN_PROCESSING:
771 /* All login PDU's received, process login request */
772 login_sm_process_request(ict);
773 break;
774 case ILS_LOGIN_RESPONDING:
775 rpdu = login_sm_build_login_response(ict);
776 login_sm_send_next_response(ict, rpdu);
777 break;
778 case ILS_LOGIN_RESPONDED:
779 /* clean up the login response idm text buffer */
780 if (lsm->icl_login_resp_itb != NULL) {
781 idm_itextbuf_free(lsm->icl_login_resp_itb);
782 lsm->icl_login_resp_itb = NULL;
783 }
784 break;
785 case ILS_LOGIN_FFP:
786 login_sm_ffp_actions(ict);
1762 } else if ((strcmp(auth, PA_AUTH_CHAP) == 0) &&
1763 (lsm->icl_auth.ca_ini_chapsecretlen == 0)) {
1764 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1765 ISCSI_LOGIN_STATUS_AUTH_FAILED);
1766 idmrc = IDM_STATUS_FAIL;
1767 }
1768
1769 ISCSIT_GLOBAL_UNLOCK();
1770
1771 return (idmrc);
1772 }
1773
1774
1775 static idm_status_t
1776 login_sm_session_register(iscsit_conn_t *ict)
1777 {
1778 iscsit_sess_t *ist = ict->ict_sess;
1779 stmf_scsi_session_t *ss;
1780 iscsi_transport_id_t *iscsi_tptid;
1781 uint16_t ident_len, adn_len, tptid_sz;
1782 char prop_buf[KSTAT_STRLEN + 1];
1783 char peer_buf[IDM_SA_NTOP_BUFSIZ];
1784
1785 /*
1786 * Hold target mutex until we have finished registering with STMF
1787 */
1788 mutex_enter(&ist->ist_tgt->target_mutex);
1789 if (ist->ist_tgt->target_state != TS_STMF_ONLINE) {
1790 mutex_exit(&ist->ist_tgt->target_mutex);
1791 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1792 ISCSI_LOGIN_STATUS_TGT_REMOVED);
1793 return (IDM_STATUS_FAIL);
1794 }
1795
1796 ss = stmf_alloc(STMF_STRUCT_SCSI_SESSION, 0,
1797 0);
1798 if (ss == NULL) {
1799 mutex_exit(&ist->ist_tgt->target_mutex);
1800 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1801 ISCSI_LOGIN_STATUS_NO_RESOURCES);
1802 return (IDM_STATUS_FAIL);
1803 }
1824 ist->ist_initiator_name, ident_len);
1825
1826 ss->ss_lport = ist->ist_lport;
1827
1828 if (stmf_register_scsi_session(ict->ict_sess->ist_lport, ss) !=
1829 STMF_SUCCESS) {
1830 mutex_exit(&ist->ist_tgt->target_mutex);
1831 kmem_free(ss->ss_rport_id,
1832 sizeof (scsi_devid_desc_t) +
1833 strlen(ist->ist_initiator_name) + 1);
1834 stmf_remote_port_free(ss->ss_rport);
1835 stmf_free(ss);
1836 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1837 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1838 return (IDM_STATUS_FAIL);
1839 }
1840
1841 ss->ss_port_private = ict->ict_sess;
1842 ict->ict_sess->ist_stmf_sess = ss;
1843 mutex_exit(&ist->ist_tgt->target_mutex);
1844 (void) snprintf(prop_buf, sizeof (prop_buf), "peername_%"PRIxPTR"",
1845 (uintptr_t)ict->ict_sess);
1846 (void) idm_sa_ntop(&ict->ict_ic->ic_raddr, peer_buf,
1847 sizeof (peer_buf));
1848 (void) stmf_add_rport_info(ss, prop_buf, peer_buf);
1849
1850 return (IDM_STATUS_SUCCESS);
1851 }
1852
1853
1854 static idm_status_t
1855 login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu)
1856 {
1857 uint8_t csg_req;
1858 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1859 iscsi_login_hdr_t *lh = (iscsi_login_hdr_t *)pdu->isp_hdr;
1860 iscsi_login_rsp_hdr_t *lh_resp = lsm->icl_login_resp_tmpl;
1861
1862 /*
1863 * Check CSG
1864 */
1865 csg_req = ISCSI_LOGIN_CURRENT_STAGE(lh->flags);
1866 switch (csg_req) {
1867 case ISCSI_SECURITY_NEGOTIATION_STAGE:
1868 case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
2747 idm_status = IDM_STATUS_FAIL;
2748 }
2749 return (idm_status);
2750 }
2751
2752 static char *
2753 iscsit_fold_name(char *name, size_t *buflen)
2754 {
2755 char *ret;
2756 const char *sns;
2757 int errnum;
2758 int flag = U8_TEXTPREP_NFKC;
2759 size_t inlen, outlen, coff;
2760
2761 if (name == NULL)
2762 return (NULL);
2763
2764 /* Check for one of the supported name types */
2765 if (strncasecmp(name, SNS_EUI ".", strlen(SNS_EUI) + 1) == 0) {
2766 sns = SNS_EUI;
2767 *buflen = SNS_EUI_LEN_MAX + 1;
2768 flag |= U8_TEXTPREP_TOUPPER;
2769 } else if (strncasecmp(name, SNS_IQN ".", strlen(SNS_IQN) + 1) == 0) {
2770 sns = SNS_IQN;
2771 *buflen = SNS_IQN_LEN_MAX + 1;
2772 flag |= U8_TEXTPREP_TOLOWER;
2773 } else if (strncasecmp(name, SNS_NAA ".", strlen(SNS_NAA) + 1) == 0) {
2774 sns = SNS_NAA;
2775 *buflen = SNS_NAA_LEN_MAX + 1;
2776 flag |= U8_TEXTPREP_TOUPPER;
2777 } else {
2778 return (NULL);
2779 }
2780
2781 ret = kmem_zalloc(*buflen, KM_SLEEP);
2782 coff = strlen(sns);
2783 inlen = strlen(name) - coff;
2784 outlen = *buflen - coff - 1;
2785
2786 /* Fold the case and normalize string */
2787 if (u8_textprep_str(name + coff, &inlen, ret + coff, &outlen, flag,
2788 U8_UNICODE_320, &errnum) == (size_t)-1) {
2789 kmem_free(ret, *buflen);
2790 return (NULL);
2791 }
2792
2793 /* Copy the name type prefix */
2794 bcopy(sns, ret, coff);
2795
2796 return (ret);
2797 }
|