xref: /dflybsd-src/sbin/iscontrol/login.c (revision 7078f92bf00cafccd0c0191c7aa92b0bb784f70e)
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