1e25c779eSMatthew Dillon /*-
2e25c779eSMatthew Dillon * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
3e25c779eSMatthew Dillon * All rights reserved.
4e25c779eSMatthew Dillon *
5e25c779eSMatthew Dillon * Redistribution and use in source and binary forms, with or without
6e25c779eSMatthew Dillon * modification, are permitted provided that the following conditions
7e25c779eSMatthew Dillon * are met:
8e25c779eSMatthew Dillon * 1. Redistributions of source code must retain the above copyright
9e25c779eSMatthew Dillon * notice, this list of conditions and the following disclaimer.
10e25c779eSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
11e25c779eSMatthew Dillon * notice, this list of conditions and the following disclaimer in the
12e25c779eSMatthew Dillon * documentation and/or other materials provided with the distribution.
13e25c779eSMatthew Dillon *
14e25c779eSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15e25c779eSMatthew Dillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16e25c779eSMatthew Dillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17e25c779eSMatthew Dillon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18e25c779eSMatthew Dillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19e25c779eSMatthew Dillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20e25c779eSMatthew Dillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21e25c779eSMatthew Dillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22e25c779eSMatthew Dillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23e25c779eSMatthew Dillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24e25c779eSMatthew Dillon * SUCH DAMAGE.
25e25c779eSMatthew Dillon *
26e25c779eSMatthew Dillon */
27e25c779eSMatthew Dillon /*
28e25c779eSMatthew Dillon | $Id: login.c,v 1.4 2007/04/27 07:40:40 danny Exp danny $
29e25c779eSMatthew Dillon */
30e25c779eSMatthew Dillon
31e25c779eSMatthew Dillon #include <sys/param.h>
32e25c779eSMatthew Dillon #include <sys/types.h>
33e25c779eSMatthew Dillon #include <sys/socket.h>
34e25c779eSMatthew Dillon #include <sys/sysctl.h>
35e25c779eSMatthew Dillon
36e25c779eSMatthew Dillon #include <netinet/in.h>
37e25c779eSMatthew Dillon #include <netinet/tcp.h>
38e25c779eSMatthew Dillon #include <arpa/inet.h>
39e25c779eSMatthew Dillon #include <sys/ioctl.h>
40e25c779eSMatthew Dillon #include <stdio.h>
41e25c779eSMatthew Dillon #include <stdlib.h>
42e25c779eSMatthew Dillon #include <string.h>
43e25c779eSMatthew Dillon
44e25c779eSMatthew Dillon #include "iscsi.h"
45e25c779eSMatthew Dillon #include "iscontrol.h"
46e25c779eSMatthew Dillon
47e25c779eSMatthew Dillon static char *status_class1[] = {
48e25c779eSMatthew Dillon "Initiator error",
49e25c779eSMatthew Dillon "Authentication failure",
50e25c779eSMatthew Dillon "Authorization failure",
51e25c779eSMatthew Dillon "Not found",
52e25c779eSMatthew Dillon "Target removed",
53e25c779eSMatthew Dillon "Unsupported version",
54e25c779eSMatthew Dillon "Too many connections",
55e25c779eSMatthew Dillon "Missing parameter",
56e25c779eSMatthew Dillon "Can't include in session",
57e25c779eSMatthew Dillon "Session type not suported",
58e25c779eSMatthew Dillon "Session does not exist",
59e25c779eSMatthew Dillon "Invalid during login",
60e25c779eSMatthew Dillon };
61e25c779eSMatthew Dillon #define CLASS1_ERRS ((sizeof status_class1) / sizeof(char *))
62e25c779eSMatthew Dillon
63e25c779eSMatthew Dillon static char *status_class3[] = {
64e25c779eSMatthew Dillon "Target error",
65e25c779eSMatthew Dillon "Service unavailable",
66e25c779eSMatthew Dillon "Out of resources"
67e25c779eSMatthew Dillon };
68e25c779eSMatthew Dillon #define CLASS3_ERRS ((sizeof status_class3) / sizeof(char *))
69e25c779eSMatthew Dillon
70e25c779eSMatthew Dillon static char *
selectFrom(char * str,token_t * list)71e25c779eSMatthew Dillon selectFrom(char *str, token_t *list)
72e25c779eSMatthew Dillon {
73e25c779eSMatthew Dillon char *sep, *sp;
74e25c779eSMatthew Dillon token_t *lp;
75e25c779eSMatthew Dillon int n;
76e25c779eSMatthew Dillon
77e25c779eSMatthew Dillon sp = str;
78e25c779eSMatthew Dillon do {
79e25c779eSMatthew Dillon sep = strchr(sp, ',');
80e25c779eSMatthew Dillon if(sep != NULL)
81e25c779eSMatthew Dillon n = sep - sp;
82e25c779eSMatthew Dillon else
83e25c779eSMatthew Dillon n = strlen(sp);
84e25c779eSMatthew Dillon
85e25c779eSMatthew Dillon for(lp = list; lp->name != NULL; lp++) {
86e25c779eSMatthew Dillon if(strncasecmp(lp->name, sp, n) == 0)
87e25c779eSMatthew Dillon return strdup(lp->name);
88e25c779eSMatthew Dillon }
89e25c779eSMatthew Dillon sp = sep + 1;
90e25c779eSMatthew Dillon } while(sep != NULL);
91e25c779eSMatthew Dillon
92e25c779eSMatthew Dillon return NULL;
93e25c779eSMatthew Dillon }
94e25c779eSMatthew Dillon
95e25c779eSMatthew Dillon static char *
getkeyval(char * key,pdu_t * pp)96e25c779eSMatthew Dillon getkeyval(char *key, pdu_t *pp)
97e25c779eSMatthew Dillon {
98e25c779eSMatthew Dillon char *ptr;
99e25c779eSMatthew Dillon int klen, len, n;
100e25c779eSMatthew Dillon
101e25c779eSMatthew Dillon debug_called(3);
102e25c779eSMatthew Dillon
103e25c779eSMatthew Dillon len = pp->ds_len;
104e25c779eSMatthew Dillon ptr = (char *)pp->ds;
105e25c779eSMatthew Dillon klen = strlen(key);
106e25c779eSMatthew Dillon while(len > klen) {
107e25c779eSMatthew Dillon if(strncmp(key, ptr, klen) == 0)
108e25c779eSMatthew Dillon return ptr+klen;
109e25c779eSMatthew Dillon n = strlen(ptr) + 1;
110e25c779eSMatthew Dillon len -= n;
111e25c779eSMatthew Dillon ptr += n;
112e25c779eSMatthew Dillon }
113e25c779eSMatthew Dillon return 0;
114e25c779eSMatthew Dillon }
115e25c779eSMatthew Dillon
116e25c779eSMatthew Dillon static int
handleTgtResp(isess_t * sess,pdu_t * pp)117e25c779eSMatthew Dillon handleTgtResp(isess_t *sess, pdu_t *pp)
118e25c779eSMatthew Dillon {
119e25c779eSMatthew Dillon isc_opt_t *op = sess->op;
120e25c779eSMatthew Dillon char *np, *rp, *d1, *d2;
121e25c779eSMatthew Dillon int res, l1, l2;
122e25c779eSMatthew Dillon
123e25c779eSMatthew Dillon res = -1;
124e25c779eSMatthew Dillon if(((np = getkeyval("CHAP_N=", pp)) == NULL) ||
125e25c779eSMatthew Dillon ((rp = getkeyval("CHAP_R=", pp)) == NULL))
126e25c779eSMatthew Dillon goto out;
127e25c779eSMatthew Dillon if(strcmp(np, op->tgtChapName? op->tgtChapName: op->initiatorName) != 0) {
128e25c779eSMatthew Dillon fprintf(stderr, "%s does not match\n", np);
129e25c779eSMatthew Dillon goto out;
130e25c779eSMatthew Dillon }
131e25c779eSMatthew Dillon l1 = str2bin(op->tgtChapDigest, &d1);
132e25c779eSMatthew Dillon l2 = str2bin(rp, &d2);
133e25c779eSMatthew Dillon
134e25c779eSMatthew Dillon debug(3, "l1=%d '%s' l2=%d '%s'", l1, op->tgtChapDigest, l2, rp);
135e25c779eSMatthew Dillon if(l1 == l2 && memcmp(d1, d2, l1) == 0)
136e25c779eSMatthew Dillon res = 0;
137e25c779eSMatthew Dillon if(l1)
138e25c779eSMatthew Dillon free(d1);
139e25c779eSMatthew Dillon if(l2)
140e25c779eSMatthew Dillon free(d2);
141e25c779eSMatthew Dillon out:
142e25c779eSMatthew Dillon free(op->tgtChapDigest);
143e25c779eSMatthew Dillon op->tgtChapDigest = NULL;
144e25c779eSMatthew Dillon
145e25c779eSMatthew Dillon debug(3, "res=%d", res);
146e25c779eSMatthew Dillon
147e25c779eSMatthew Dillon return res;
148e25c779eSMatthew Dillon }
149e25c779eSMatthew Dillon
150e25c779eSMatthew Dillon static void
processParams(isess_t * sess,pdu_t * pp)151e25c779eSMatthew Dillon processParams(isess_t *sess, pdu_t *pp)
152e25c779eSMatthew Dillon {
153e25c779eSMatthew Dillon isc_opt_t *op = sess->op;
154e25c779eSMatthew Dillon int len, klen, n;
155e25c779eSMatthew Dillon char *eq, *ptr;
156e25c779eSMatthew Dillon
157e25c779eSMatthew Dillon debug_called(3);
158e25c779eSMatthew Dillon
159e25c779eSMatthew Dillon len = pp->ds_len;
160e25c779eSMatthew Dillon ptr = (char *)pp->ds;
161e25c779eSMatthew Dillon while(len > 0) {
162e25c779eSMatthew Dillon if(vflag > 1)
163e25c779eSMatthew Dillon printf("got: len=%d %s\n", len, ptr);
164e25c779eSMatthew Dillon klen = 0;
165e25c779eSMatthew Dillon if((eq = strchr(ptr, '=')) != NULL)
166e25c779eSMatthew Dillon klen = eq - ptr;
167e25c779eSMatthew Dillon if(klen > 0) {
168e25c779eSMatthew Dillon if(strncmp(ptr, "TargetAddress", klen) == 0) {
169e25c779eSMatthew Dillon char *p, *q, *ta = NULL;
170e25c779eSMatthew Dillon
171e25c779eSMatthew Dillon // TargetAddress=domainname[:port][,portal-group-tag]
172e25c779eSMatthew Dillon // XXX: if(op->targetAddress) free(op->targetAddress);
173e25c779eSMatthew Dillon q = op->targetAddress = strdup(eq+1);
174e25c779eSMatthew Dillon if(*q == '[') {
175e25c779eSMatthew Dillon // bracketed IPv6
176e25c779eSMatthew Dillon if((q = strchr(q, ']')) != NULL) {
177e25c779eSMatthew Dillon *q++ = '\0';
178e25c779eSMatthew Dillon ta = op->targetAddress;
179e25c779eSMatthew Dillon op->targetAddress = strdup(ta+1);
180e25c779eSMatthew Dillon } else
181e25c779eSMatthew Dillon q = op->targetAddress;
182e25c779eSMatthew Dillon }
183e25c779eSMatthew Dillon if((p = strchr(q, ',')) != NULL) {
184e25c779eSMatthew Dillon *p++ = 0;
185e25c779eSMatthew Dillon op->targetPortalGroupTag = atoi(p);
186e25c779eSMatthew Dillon }
187e25c779eSMatthew Dillon if((p = strchr(q, ':')) != NULL) {
188e25c779eSMatthew Dillon *p++ = 0;
189e25c779eSMatthew Dillon op->port = atoi(p);
190e25c779eSMatthew Dillon }
191e25c779eSMatthew Dillon if(ta)
192e25c779eSMatthew Dillon free(ta);
193e25c779eSMatthew Dillon } else if(strncmp(ptr, "MaxRecvDataSegmentLength", klen) == 0) {
194e25c779eSMatthew Dillon // danny's RFC
195*832b6303SSascha Wildner op->maxXmitDataSegmentLength = strtol(eq+1, NULL, 0);
196e25c779eSMatthew Dillon } else if(strncmp(ptr, "TargetPortalGroupTag", klen) == 0) {
197*832b6303SSascha Wildner op->targetPortalGroupTag = strtol(eq+1, NULL, 0);
198e25c779eSMatthew Dillon } else if(strncmp(ptr, "HeaderDigest", klen) == 0) {
199e25c779eSMatthew Dillon op->headerDigest = selectFrom(eq+1, DigestMethods);
200e25c779eSMatthew Dillon } else if(strncmp(ptr, "DataDigest", klen) == 0) {
201e25c779eSMatthew Dillon op->dataDigest = selectFrom(eq+1, DigestMethods);
202e25c779eSMatthew Dillon } else if(strncmp(ptr, "MaxOutstandingR2T", klen) == 0)
203*832b6303SSascha Wildner op->maxOutstandingR2T = strtol(eq+1, NULL, 0);
204e25c779eSMatthew Dillon #if 0
205e25c779eSMatthew Dillon else
206e25c779eSMatthew Dillon for(kp = keyMap; kp->name; kp++) {
207e25c779eSMatthew Dillon if(strncmp(ptr, kp->name, kp->len) == 0 && ptr[kp->len] == '=')
208e25c779eSMatthew Dillon mp->func(sess, ptr+kp->len+1, GET);
209e25c779eSMatthew Dillon }
210e25c779eSMatthew Dillon #endif
211e25c779eSMatthew Dillon }
212e25c779eSMatthew Dillon n = strlen(ptr) + 1;
213e25c779eSMatthew Dillon len -= n;
214e25c779eSMatthew Dillon ptr += n;
215e25c779eSMatthew Dillon }
216e25c779eSMatthew Dillon
217e25c779eSMatthew Dillon }
218e25c779eSMatthew Dillon
219e25c779eSMatthew Dillon static int
handleLoginResp(isess_t * sess,pdu_t * pp)220e25c779eSMatthew Dillon handleLoginResp(isess_t *sess, pdu_t *pp)
221e25c779eSMatthew Dillon {
222e25c779eSMatthew Dillon login_rsp_t *lp = (login_rsp_t *)pp;
223e25c779eSMatthew Dillon uint st_class, status = ntohs(lp->status);
224e25c779eSMatthew Dillon
225e25c779eSMatthew Dillon debug_called(3);
226e25c779eSMatthew Dillon debug(4, "Tbit=%d csg=%d nsg=%d status=%x", lp->T, lp->CSG, lp->NSG, status);
227e25c779eSMatthew Dillon
228e25c779eSMatthew Dillon st_class = status >> 8;
229e25c779eSMatthew Dillon if(status) {
230e25c779eSMatthew Dillon unsigned int st_detail = status & 0xff;
231e25c779eSMatthew Dillon
232e25c779eSMatthew Dillon switch(st_class) {
233e25c779eSMatthew Dillon case 1: // Redirect
234e25c779eSMatthew Dillon switch(st_detail) {
235e25c779eSMatthew Dillon // the ITN (iSCSI target Name) requests a:
236e25c779eSMatthew Dillon case 1: // temporary address change
237e25c779eSMatthew Dillon case 2: // permanent address change
238e25c779eSMatthew Dillon status = 0;
239e25c779eSMatthew Dillon }
240e25c779eSMatthew Dillon break;
241e25c779eSMatthew Dillon
242e25c779eSMatthew Dillon case 2: // Initiator Error
243e25c779eSMatthew Dillon if(st_detail < CLASS1_ERRS)
244e25c779eSMatthew Dillon printf("0x%04x: %s\n", status, status_class1[st_detail]);
245e25c779eSMatthew Dillon break;
246e25c779eSMatthew Dillon
247e25c779eSMatthew Dillon case 3:
248e25c779eSMatthew Dillon if(st_detail < CLASS3_ERRS)
249e25c779eSMatthew Dillon printf("0x%04x: %s\n", status, status_class3[st_detail]);
250e25c779eSMatthew Dillon break;
251e25c779eSMatthew Dillon }
252e25c779eSMatthew Dillon }
253e25c779eSMatthew Dillon
254e25c779eSMatthew Dillon if(status == 0) {
255e25c779eSMatthew Dillon processParams(sess, pp);
256e25c779eSMatthew Dillon setOptions(sess, 0); // XXX: just in case ...
257e25c779eSMatthew Dillon
258e25c779eSMatthew Dillon if(lp->T) {
259e25c779eSMatthew Dillon isc_opt_t *op = sess->op;
260e25c779eSMatthew Dillon
261e25c779eSMatthew Dillon if(sess->csg == SN_PHASE && (op->tgtChapDigest != NULL))
262e25c779eSMatthew Dillon if(handleTgtResp(sess, pp) != 0)
263e25c779eSMatthew Dillon return 1; // XXX: Authentication failure ...
264e25c779eSMatthew Dillon sess->csg = lp->NSG;
265e25c779eSMatthew Dillon if(sess->csg == FF_PHASE) {
266e25c779eSMatthew Dillon // XXX: will need this when implementing reconnect.
267e25c779eSMatthew Dillon sess->tsih = lp->tsih;
268e25c779eSMatthew Dillon debug(2, "TSIH=%x", sess->tsih);
269e25c779eSMatthew Dillon }
270e25c779eSMatthew Dillon }
271e25c779eSMatthew Dillon }
272e25c779eSMatthew Dillon
273e25c779eSMatthew Dillon return st_class;
274e25c779eSMatthew Dillon }
275e25c779eSMatthew Dillon
276e25c779eSMatthew Dillon static int
handleChap(isess_t * sess,pdu_t * pp)277e25c779eSMatthew Dillon handleChap(isess_t *sess, pdu_t *pp)
278e25c779eSMatthew Dillon {
279e25c779eSMatthew Dillon pdu_t spp;
280e25c779eSMatthew Dillon login_req_t *lp;
281e25c779eSMatthew Dillon isc_opt_t *op = sess->op;
282e25c779eSMatthew Dillon char *ap, *ip, *cp, *digest; // MD5 is 128bits, SHA1 160bits
283e25c779eSMatthew Dillon
284e25c779eSMatthew Dillon debug_called(3);
285e25c779eSMatthew Dillon
286e25c779eSMatthew Dillon bzero(&spp, sizeof(pdu_t));
287e25c779eSMatthew Dillon lp = (login_req_t *)&spp.ipdu.bhs;
288e25c779eSMatthew Dillon lp->cmd = ISCSI_LOGIN_CMD | 0x40; // login request + Inmediate
289e25c779eSMatthew Dillon memcpy(lp->isid, sess->isid, 6);
290e25c779eSMatthew Dillon lp->tsih = sess->tsih; // MUST be zero the first time!
291e25c779eSMatthew Dillon lp->CID = htons(1);
292e25c779eSMatthew Dillon lp->CSG = SN_PHASE; // Security Negotiation
293e25c779eSMatthew Dillon lp->NSG = LON_PHASE;
294e25c779eSMatthew Dillon lp->T = 1;
295e25c779eSMatthew Dillon
296e25c779eSMatthew Dillon if(((ap = getkeyval("CHAP_A=", pp)) == NULL) ||
297e25c779eSMatthew Dillon ((ip = getkeyval("CHAP_I=", pp)) == NULL) ||
298e25c779eSMatthew Dillon ((cp = getkeyval("CHAP_C=", pp)) == NULL))
299e25c779eSMatthew Dillon return -1;
300e25c779eSMatthew Dillon
301*832b6303SSascha Wildner if((digest = chapDigest(ap, (char)strtol(ip, NULL, 0), cp, op->chapSecret)) == NULL)
302e25c779eSMatthew Dillon return -1;
303e25c779eSMatthew Dillon
304e25c779eSMatthew Dillon addText(&spp, "CHAP_N=%s", op->chapIName? op->chapIName: op->initiatorName);
305e25c779eSMatthew Dillon addText(&spp, "CHAP_R=%s", digest);
306e25c779eSMatthew Dillon free(digest);
307e25c779eSMatthew Dillon
308e25c779eSMatthew Dillon if(op->tgtChapSecret != NULL) {
309e25c779eSMatthew Dillon op->tgtChapID = (random() >> 24) % 255; // should be random enough ...
310e25c779eSMatthew Dillon addText(&spp, "CHAP_I=%d", op->tgtChapID);
311e25c779eSMatthew Dillon cp = genChapChallenge(cp, op->tgtChallengeLen? op->tgtChallengeLen: 8);
312e25c779eSMatthew Dillon addText(&spp, "CHAP_C=%s", cp);
313e25c779eSMatthew Dillon op->tgtChapDigest = chapDigest(ap, op->tgtChapID, cp, op->tgtChapSecret);
314e25c779eSMatthew Dillon }
315e25c779eSMatthew Dillon
316e25c779eSMatthew Dillon return sendPDU(sess, &spp, handleLoginResp);
317e25c779eSMatthew Dillon }
318e25c779eSMatthew Dillon
319e25c779eSMatthew Dillon static int
authenticate(isess_t * sess)320e25c779eSMatthew Dillon authenticate(isess_t *sess)
321e25c779eSMatthew Dillon {
322e25c779eSMatthew Dillon pdu_t spp;
323e25c779eSMatthew Dillon login_req_t *lp;
324e25c779eSMatthew Dillon isc_opt_t *op = sess->op;
325e25c779eSMatthew Dillon
326e25c779eSMatthew Dillon bzero(&spp, sizeof(pdu_t));
327e25c779eSMatthew Dillon lp = (login_req_t *)&spp.ipdu.bhs;
328e25c779eSMatthew Dillon lp->cmd = ISCSI_LOGIN_CMD | 0x40; // login request + Inmediate
329e25c779eSMatthew Dillon memcpy(lp->isid, sess->isid, 6);
330e25c779eSMatthew Dillon lp->tsih = sess->tsih; // MUST be zero the first time!
331e25c779eSMatthew Dillon lp->CID = htons(1);
332e25c779eSMatthew Dillon lp->CSG = SN_PHASE; // Security Negotiation
333e25c779eSMatthew Dillon lp->NSG = SN_PHASE;
334e25c779eSMatthew Dillon lp->T = 0;
335e25c779eSMatthew Dillon
336e25c779eSMatthew Dillon switch((authm_t)lookup(AuthMethods, op->authMethod)) {
337e25c779eSMatthew Dillon case NONE:
338e25c779eSMatthew Dillon return 0;
339e25c779eSMatthew Dillon
340e25c779eSMatthew Dillon case KRB5:
341e25c779eSMatthew Dillon case SPKM1:
342e25c779eSMatthew Dillon case SPKM2:
343e25c779eSMatthew Dillon case SRP:
344e25c779eSMatthew Dillon return 2;
345e25c779eSMatthew Dillon
346e25c779eSMatthew Dillon case CHAP:
347e25c779eSMatthew Dillon if(op->chapDigest == 0)
348e25c779eSMatthew Dillon addText(&spp, "CHAP_A=5");
349e25c779eSMatthew Dillon else
350e25c779eSMatthew Dillon if(strcmp(op->chapDigest, "MD5") == 0)
351e25c779eSMatthew Dillon addText(&spp, "CHAP_A=5");
352e25c779eSMatthew Dillon else
353e25c779eSMatthew Dillon if(strcmp(op->chapDigest, "SHA1") == 0)
354e25c779eSMatthew Dillon addText(&spp, "CHAP_A=7");
355e25c779eSMatthew Dillon else
356e25c779eSMatthew Dillon addText(&spp, "CHAP_A=5,7");
357e25c779eSMatthew Dillon return sendPDU(sess, &spp, handleChap);
358e25c779eSMatthew Dillon }
359e25c779eSMatthew Dillon return 1;
360e25c779eSMatthew Dillon }
361e25c779eSMatthew Dillon
362e25c779eSMatthew Dillon int
loginPhase(isess_t * sess)363e25c779eSMatthew Dillon loginPhase(isess_t *sess)
364e25c779eSMatthew Dillon {
365e25c779eSMatthew Dillon pdu_t spp, *sp = &spp;
366e25c779eSMatthew Dillon isc_opt_t *op = sess->op;
367e25c779eSMatthew Dillon login_req_t *lp;
368e25c779eSMatthew Dillon int status = 1;
369e25c779eSMatthew Dillon
370e25c779eSMatthew Dillon debug_called(3);
371e25c779eSMatthew Dillon
372e25c779eSMatthew Dillon bzero(sp, sizeof(pdu_t));
373e25c779eSMatthew Dillon lp = (login_req_t *)&spp.ipdu.bhs;
374e25c779eSMatthew Dillon lp->cmd = ISCSI_LOGIN_CMD | 0x40; // login request + Inmediate
375e25c779eSMatthew Dillon memcpy(lp->isid, sess->isid, 6);
376e25c779eSMatthew Dillon lp->tsih = sess->tsih; // MUST be zero the first time!
377e25c779eSMatthew Dillon lp->CID = htons(1); // sess->cid?
378e25c779eSMatthew Dillon
379e25c779eSMatthew Dillon if((lp->CSG = sess->csg) == LON_PHASE)
380e25c779eSMatthew Dillon lp->NSG = FF_PHASE; // lets try and go full feature ...
381e25c779eSMatthew Dillon else
382e25c779eSMatthew Dillon lp->NSG = LON_PHASE;
383e25c779eSMatthew Dillon lp->T = 1; // transit to next login stage
384e25c779eSMatthew Dillon
385e25c779eSMatthew Dillon if(sess->flags & SESS_INITIALLOGIN1) {
386e25c779eSMatthew Dillon sess->flags &= ~SESS_INITIALLOGIN1;
387e25c779eSMatthew Dillon
388e25c779eSMatthew Dillon addText(sp, "SessionType=%s", op->sessionType);
389e25c779eSMatthew Dillon addText(sp, "InitiatorName=%s", op->initiatorName);
390e25c779eSMatthew Dillon if(strcmp(op->sessionType, "Discovery") != 0) {
391e25c779eSMatthew Dillon addText(sp, "TargetName=%s", op->targetName);
392e25c779eSMatthew Dillon }
393e25c779eSMatthew Dillon }
394e25c779eSMatthew Dillon switch(sess->csg) {
395e25c779eSMatthew Dillon case SN_PHASE: // Security Negotiation
396e25c779eSMatthew Dillon addText(sp, "AuthMethod=%s", op->authMethod);
397e25c779eSMatthew Dillon break;
398e25c779eSMatthew Dillon
399e25c779eSMatthew Dillon case LON_PHASE: // Login Operational Negotiation
400e25c779eSMatthew Dillon if((sess->flags & SESS_NEGODONE) == 0) {
401e25c779eSMatthew Dillon sess->flags |= SESS_NEGODONE;
402e25c779eSMatthew Dillon addText(sp, "MaxBurstLength=%d", op->maxBurstLength);
403e25c779eSMatthew Dillon addText(sp, "HeaderDigest=%s", op->headerDigest);
404e25c779eSMatthew Dillon addText(sp, "DataDigest=%s", op->dataDigest);
405e25c779eSMatthew Dillon addText(sp, "MaxRecvDataSegmentLength=%d", op->maxRecvDataSegmentLength);
406e25c779eSMatthew Dillon addText(sp, "ErrorRecoveryLevel=%d", op->errorRecoveryLevel);
407e25c779eSMatthew Dillon addText(sp, "DefaultTime2Wait=%d", op->defaultTime2Wait);
408e25c779eSMatthew Dillon addText(sp, "DefaultTime2Retain=%d", op->defaultTime2Retain);
409e25c779eSMatthew Dillon addText(sp, "DataPDUInOrder=%s", op->dataPDUInOrder? "Yes": "No");
410e25c779eSMatthew Dillon addText(sp, "DataSequenceInOrder=%s", op->dataSequenceInOrder? "Yes": "No");
411e25c779eSMatthew Dillon addText(sp, "MaxOutstandingR2T=%d", op->maxOutstandingR2T);
412e25c779eSMatthew Dillon
413e25c779eSMatthew Dillon if(strcmp(op->sessionType, "Discovery") != 0) {
414e25c779eSMatthew Dillon addText(sp, "MaxConnections=%d", op->maxConnections);
415e25c779eSMatthew Dillon addText(sp, "FirstBurstLength=%d", op->firstBurstLength);
416e25c779eSMatthew Dillon addText(sp, "InitialR2T=%s", op->initialR2T? "Yes": "No");
417e25c779eSMatthew Dillon addText(sp, "ImmediateData=%s", op->immediateData? "Yes": "No");
418e25c779eSMatthew Dillon }
419e25c779eSMatthew Dillon }
420e25c779eSMatthew Dillon
421e25c779eSMatthew Dillon break;
422e25c779eSMatthew Dillon }
423e25c779eSMatthew Dillon
424e25c779eSMatthew Dillon status = sendPDU(sess, &spp, handleLoginResp);
425e25c779eSMatthew Dillon
426e25c779eSMatthew Dillon switch(status) {
427e25c779eSMatthew Dillon case 0: // all is ok ...
428e25c779eSMatthew Dillon if(sess->csg == SN_PHASE)
429e25c779eSMatthew Dillon /*
430e25c779eSMatthew Dillon | if we are still here, then we need
431e25c779eSMatthew Dillon | to exchange some secrets ...
432e25c779eSMatthew Dillon */
433e25c779eSMatthew Dillon status = authenticate(sess);
434e25c779eSMatthew Dillon }
435e25c779eSMatthew Dillon
436e25c779eSMatthew Dillon return status;
437e25c779eSMatthew Dillon }
438