Пример #1
0
Файл: smtp.c Проект: gitpan/zxid
/* Called by:  smtp_decode_req */
static int smtp_ehlo(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* req)
{
  char* p = req->m;
  char* lim = req->ap;
  
  if (lim - p < 7) {   /* too little, need more for "EHLO s\n" */
    req->need = 7 - (lim - p);
    return 0;
  }
  
  p[0] = toupper(p[0]);
  p[1] = toupper(p[1]);
  p[2] = toupper(p[2]);
  p[3] = toupper(p[3]);
  if (memcmp(p, "EHLO ", 5) && memcmp(req->m, "HELO ", 5)) goto bad;
  p += 5;
  
  for (; p < lim && !ONE_OF_2(*p, '\r', '\n'); ++p) ;
  CRLF_CHECK(p, lim, req);

  hi_sendf(hit, io, 0, 0, "250-%s\r\n250-PIPELINING\r\n250 8-BIT MIME\r\n", SMTP_EHLO_CLI);
  io->pair = hi_prototab[HIPROTO_SIS].specs->conns;
  hi_prototab[HIPROTO_SIS].specs->conns->pair = io;  /* But there could be multiple? */
#if 0   /* We do this nowdays during setup */
  sis_send_bind(hit, io->pair, SAP_ID_HMTP, 0, 0x0200);  /* 0x0200 == nonarq, no repeats */
#endif
  io->ad.smtp.state = SMTP_MAIN;
  req->need = (p - req->m) + 5;
  req->ad.smtp.skip_ehlo = req->scan = p;
  D("EHLO ok req(%p)", req);
  return 0;
 bad:
  ERR("Bad SMTP PDU. fd(%x)", io->fd);
  return HI_CONN_CLOSE;
}
Пример #2
0
/* Called by:  zxcot_main */
static int zxid_lscot(zxid_conf* cf, int col_swap, const char* dcot)
{
  int got, ret;
  char* p;
  DIR* dir;
  struct dirent* de;

  dir = opendir(dcot);
  if (!dir) {
    perror("opendir for /var/zxid/cot (or other if configured) for loading cot cache");
    D("failed path(%s)", dcot);
    
    got = strlen(dcot);
    p = ZX_ALLOC(cf->ctx, got+1);
    memcpy(p, dcot, got-1);
    p[got-1] = 0;  /* chop off / */
    got = zxid_lscot_line(cf, col_swap, p, "");
    ZX_FREE(cf->ctx, p);
    return got;
  }
  
  while (de = readdir(dir)) {
    if (de->d_name[0] == '.' || de->d_name[strlen(de->d_name)-1] == '~')
      continue;
    ret = zxid_lscot_line(cf, col_swap, dcot, de->d_name);
    if (!ONE_OF_2(ret, 0, 2))
      return ret;
  }
  return 0;
}
Пример #3
0
Файл: smtp.c Проект: gitpan/zxid
/* Called by:  smtp_decode_resp */
static int smtp_resp_wait_221_goodbye(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* resp)
{
  char* p = resp->scan;
  char* lim = resp->ap;
  int n = lim - p;
  
  if (n < 6) {  /* 250 m\n or 250-m\n */
    resp->need = (6 - n) + (p - resp->m);  /* what we have plus what we need */
    return 0;
  }
  
  if (!THREE_IN_ROW(p, '2', '2', '1'))     /* 221 goodbye */
    goto bad;
  
  switch (n = p[3]) {
  case ' ':
  case '-':
    for (p+=4; p < lim && !ONE_OF_2(*p, '\r', '\n'); ++p) ;
    CRLF_CHECK(p, lim, resp);
    resp->scan = p;
    break;
  default: goto bad;
  }
  if (n == ' ') {
    D("221 bye seen resp(%p)", resp);
    io->ad.smtp.state = SMTP_INIT;
    return HI_CONN_CLOSE;
  }
  resp->need = 6 + p - resp->m;  /* Prime the pump for next response */
  return 0;
  
 bad:
  D("SMTP server sent bad response(%.*s)", n, p);
  return HI_CONN_CLOSE;
}
Пример #4
0
/* Called by:  hi_shuffle */
struct hi_qel* hi_todo_consume(struct hi_thr* hit)
{
  struct hi_io* io;
  struct hi_qel* qe;
  LOCK(hit->shf->todo_mut, "todo_cons");
  D("LOCK todo_mut.thr=%lx (cond_wait)", (long)hit->shf->todo_mut.thr);

 deque_again:
  while (!hit->shf->todo_consume && hit->shf->poll_tok.proto == HIPROTO_POLL_OFF)  /* Empty? */
    ERRMAC_COND_WAIT(&hit->shf->todo_cond, hit->shf->todo_mut, "todo-cons"); /* Block until work */
  D("Out of cond_wait todo_mut.thr=%lx", (long)hit->shf->todo_mut.thr);
  
  if (!hit->shf->todo_consume) {
    ASSERT(hit->shf->poll_tok.proto);
  force_poll:
    hit->shf->poll_tok.proto = HIPROTO_POLL_OFF;
    D("UNLK cons-poll todo_mut.thr=%lx", (long)hit->shf->todo_mut.thr);
    UNLOCK(hit->shf->todo_mut, "todo_cons-poll");
    return &hit->shf->poll_tok;
  }
  
  qe = hi_todo_consume_queue_inlock(hit->shf);
  if (!ONE_OF_2(qe->kind, HI_TCP_S, HI_TCP_C)) {
    D("cons qe_%p kind(%s) intodo=%x todo_mut.thr=%lx", qe, QEL_KIND(qe->kind), qe->intodo, (long)hit->shf->todo_mut.thr);
    UNLOCK(hit->shf->todo_mut, "todo_cons");
    return qe;
  }
  
  io = (struct hi_io*)qe;
  LOCK(io->qel.mut, "n_thr-inc");
  ASSERT(!hit->cur_io);
  if (io->n_thr == HI_IO_N_THR_END_POLL) {      /* Special close end game, see hi_close() */
    io->n_thr = HI_IO_N_THR_END_GAME;
    hi_todo_produce_queue_inlock(hit->shf, qe); /* Put it back: try again later */
    UNLOCK(io->qel.mut, "n_thr-poll");
    goto force_poll;
  }
  if (io->n_thr == HI_IO_N_THR_END_GAME) {
    hit->cur_io = io;
    hit->cur_n_close = io->n_close;
    UNLOCK(io->qel.mut, "n_thr-end");
    hi_close(hit, io, "cons-end");
    goto deque_again;
  }
  if (io->fd & 0x80000000) {
    D("cons-ign-closed: LK&UNLK io(%x)->qel.thr=%lx n_thr=%d r/w=%d/%d ev=%d intodo=%x", io->fd, (long)io->qel.mut.thr, io->n_thr, io->reading, io->writing, io->events, io->qel.intodo);
    /* Let it be consumed so that r/w will fail and hi_close() is called to clean up. */
  }
  
  ++io->n_thr;  /* Increase two counts: once for write, and once for read, decrease for intodo ending. Net is +1. */
  hit->cur_io = io;
  hit->cur_n_close = io->n_close;
  D("cons: LK&UNLK io(%x)->qel.thr=%lx n_thr=%d r/w=%d/%d ev=%x intodo=%x", io->fd, (long)io->qel.mut.thr, io->n_thr, io->reading, io->writing, io->events, io->qel.intodo);
  UNLOCK(io->qel.mut, "n_thr-inc");
  D("UNLK todo_mut.thr=%lx", (long)hit->shf->todo_mut.thr);
  UNLOCK(hit->shf->todo_mut, "todo_cons-tcp");
  return qe;
}
Пример #5
0
Файл: smtp.c Проект: gitpan/zxid
/* Called by:  smtp_decode_req */
static int smtp_data(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* req)
{
  char* p = req->scan;
  char* lim = req->ap;
  
  switch (io->ad.smtp.state) {
  case SMTP_MORE0: break;
  case SMTP_MORE1: goto look_for_dot;
  case SMTP_MORE2:
  default: NEVERNEVER("impossible SMTP state %d", io->ad.smtp.state);
  }
  
  while (lim - p >= 3) {    /* \n.\n */
    for (; *p != '\n' && lim - p >= 3; ++p) ; /* \n.\n */
    if (lim - p < 3)
      break;
    ++p;
  look_for_dot:
    if (p[0] == '.' && ONE_OF_2(p[1], '\r', '\n')) {
      ++p;
      if (*p == '\r') {
	++p;
	if (p == lim) break;
	if (*p != '\n') continue;   /* this happens a lot */
      }
      ++p;   /* *p was '\n' */
      
      /* End of message, hurrah! */
      
      D("End-of-message seen req(%p)", req);
      hmtp_send(hit, io->pair, p - req->m, req->m, 6, "QUIT\r\n");
#if 1
      io->ad.smtp.state = SMTP_WAIT;
      req->need = 0;  /* Hold it until we get response from SIS layer. */
#else
      hi_sendf(hit, io, 0, 0, "250 sent\r\n");   /* *** hold this off? */
      req->need = (p - req->m) + 5;
      /* *** not clear how second message could be sent. Perhaps we need second scan pointer? */
#endif
      req->scan = p;
      return 0;
    }
  }
  /* *** need to handle mail larger than U_PDU case */
  req->need = 3 - (lim - p);
  req->scan = p-1;
  D("more data needed req(%p) need=%d", req, req->need);
  return 0;
  
 bad:
  ERR("Bad SMTP PDU. fd(%x)", io->fd);
  return HI_CONN_CLOSE;
}
Пример #6
0
/* Called by:  hi_accept, hi_accept_book, hi_close, hi_in_out, hi_poll x3, hi_send0, stomp_msg_deliver, zxbus_sched_new_delivery, zxbus_sched_pending_delivery */
void hi_todo_produce(struct hi_thr* hit, struct hi_qel* qe, const char* lk, int from_poll)
{
  struct hi_io* io;
  LOCK(hit->shf->todo_mut, "todo_prod");
  D("%s: LOCK todo_mut.thr=%lx", lk, (long)hit->shf->todo_mut.thr);

  if (qe->intodo == HI_INTODO_INTODO) {
    if (ONE_OF_2(qe->kind, HI_TCP_S, HI_TCP_C)) {
      io = ((struct hi_io*)qe);
      D("%s: prod already in todo(%x) n_thr=%d r/w=%d/%d ev=%x", lk, io->fd, io->n_thr, io->reading, io->writing, io->events);
      if (io->fd & 0x80000000)
	D("%s: prod-closed fd(%x) intodo! n_thr=%d r/w=%d/%d ev=%x intodo=%x", lk, io->fd, io->n_thr, io->reading, io->writing, io->events, io->qel.intodo);
    } else {
      D("%s: prod already in todo qe_%p kind(%s)", lk, qe, QEL_KIND(qe->kind));
    }
    goto out;
  }
  
  if (!ONE_OF_2(qe->kind, HI_TCP_S, HI_TCP_C)) {
    D("%s: prod qe(%p) kind(%s)", lk, qe, QEL_KIND(qe->kind));
    goto produce;
  }

  io = (struct hi_io*)qe;
  LOCK(io->qel.mut, "n_thr-inc-todo");
  if (from_poll) {
    /* Detect already closed (or even end game) io, see hi_close(). Note that
     * this detection only needs to apply to produce from poll. */
    if (io->n_thr == HI_IO_N_THR_END_POLL || io->fd & 0x80000000) {
      D("%s: prod(%x)-ign LK&UNLK n_c/t=%d/%d r/w=%d/%d ev=%x", lk, io->fd, io->n_close, io->n_thr, io->reading, io->writing, io->events);
      UNLOCK(io->qel.mut, "n_thr-inc-ign");
      goto out;
    }
    ASSERTOPI(io->n_thr, >=, 0);
    ++io->n_thr;  /* Should have been done already by caller, but for poll optimize lock. */
  } else {
    if (io->n_thr != HI_IO_N_THR_END_POLL) {
Пример #7
0
/* Called by:  stomp_msg_deliver, zxbus_subscribe */
struct hi_ch* zxbus_find_ch(struct hiios* shf, int len, const char* dest)
{
    int n;
    struct hi_ch* ch;
    if (len == -1)
        len = strlen(dest);
    else if (len == -2)
        len = strchr(dest, '\n') - dest;
    for (n = shf->max_chs, ch = shf->chs; n; --n, ++ch) {
        if (!ch->dest)
            break;
        if (!memcmp(ch->dest, dest, len) && ONE_OF_2(dest[len],'\n','\0')) {
            D("found ch(%s)", ch->dest);
            return ch;
        }
    }
    D("channel(%.*s) not found", len, dest);
    return 0;
}
Пример #8
0
Файл: zxpw.c Проект: kiwiroy/zx
/* Called by:  zx_password_authn */
static int zx_pw_chk(const char* uid, const char* pw_buf, const char* passw, int fd_hint)
{
  unsigned char pw_hash[120];
  
  /* *** Add here support for other authentication backends */
  
  DD("io(%x) pw_buf (%s) len=%d", fd_hint, pw_buf, strlen(pw_buf));
  
  if (!memcmp(pw_buf, "$1$", sizeof("$1$")-1)) {              /* MD5 hashed password */
    zx_md5_crypt(passw, (char*)pw_buf, (char*)pw_hash);
    D("io(%x) pw_hash(%s)", fd_hint, pw_hash);
    if (strcmp((char*)pw_buf, (char*)pw_hash)) {
      ERR("Bad password. uid(%s)", uid);
      D("md5 pw(%s) .pw(%s) pw_hash(%s)", passw, pw_buf, pw_hash);
      return 0;
    }
#ifdef USE_OPENSSL
  } else if (!memcmp(pw_buf, "$c$", sizeof("$c$")-1)) {       /* DES fcrypt hashed password */
    DES_fcrypt(passw, (char*)pw_buf+3, (char*)pw_hash);
    D("io(%x) pw_hash(%s)", fd_hint, pw_hash);
    if (strcmp((char*)pw_buf+3, (char*)pw_hash)) {
      ERR("Bad password for uid(%s)", uid);
      D("crypt pw(%s) .pw(%s) pw_hash(%s)", passw, pw_buf, pw_hash);
      return 0;
    }
#endif
  } else if (ONE_OF_2(pw_buf[0], '$', '_')) {                 /* Unsupported hash */
    ERR("Unsupported password hash. uid(%s)", uid);
    D("io(%x) pw(%s) .pw(%s)", fd_hint, passw, pw_buf);
    return 0;
  } else {                                                    /* Plaintext password (no hash) */
    if (strcmp((char*)pw_buf, passw)) {
      ERR("Bad password. uid(%s)", uid);
      D("io(%x) pw(%s) .pw(%s)", fd_hint, passw, pw_buf);
      return 0;
    }
  }
  INFO("Login(%x) OK acnt(%s)", fd_hint, uid);
  return 2;
}
Пример #9
0
Файл: smtp.c Проект: gitpan/zxid
/* Called by:  smtp_decode_resp */
static int smtp_resp_wait_250_msg_sent(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* resp)
{
  char* p = resp->scan;
  char* lim = resp->ap;
  int n = lim - p;
  
  if (n < 6) {  /* 250 m\n or 250-m\n */
    resp->need = (6 - n) + (p - resp->m);  /* what we have plus what we need */
    return 0;
  }
  
  if (!THREE_IN_ROW(p, '2', '5', '0'))     /* 250 message sent */
    goto bad;
  
  switch (n = p[3]) {
  case ' ':
  case '-':
    for (p+=4; p < lim && !ONE_OF_2(*p, '\r', '\n'); ++p) ;
    CRLF_CHECK(p, lim, resp);
    resp->scan = p;
    break;
  default: goto bad;
  }
  if (n == ' ') {
    /* *** should we attempt to skip the 220 greeting? */
    D("250 after data 354 seen resp(%p)", resp);
    hmtp_send(hit, io->pair, p-resp->m, resp->m, 13, "221 goodbye\r\n");
    hi_sendf(hit, io, 0, 0, "QUIT\r\n");   /* One message per connection! */
    io->ad.smtp.state = SMTP_QUIT;
  }
  resp->need = 6 + p - resp->m;  /* Prime the pump for next response */
  return 0;
  
 bad:
  D("SMTP server sent bad response(%.*s)", n, p);
  if (io->pair)
    hmtp_send(hit, io->pair, resp->need, resp->m, 0, 0);
  return HI_CONN_CLOSE;
}
Пример #10
0
Файл: smtp.c Проект: gitpan/zxid
/* Called by:  smtp_decode_resp */
static int smtp_resp_wait_220_greet(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* resp)
{
  char* p = resp->scan;
  char* lim = resp->ap;
  int n = lim - p;
  
  if (n < 6) {  /* 220 m\n or 220-m\n */
    resp->need = (6 - n) + (p - resp->m);  /* what we have plus what we need */
    return 0;
  }
  
  if (!THREE_IN_ROW(p, '2', '2', '0'))  /* 220 greet */
    goto bad;
  
  switch (n = p[3]) {
  case ' ':
  case '-':
    for (p+=4; p < lim && !ONE_OF_2(*p, '\r', '\n'); ++p) ;
    CRLF_CHECK(p, lim, resp);
    resp->scan = p;
    break;
  default: goto bad;
  }
  if (n == ' ') {
    D("220 greet seen resp(%p)", resp);
    hi_sendf(hit, io, 0, 0, "EHLO %s\r\n", SMTP_GREET_DOMAIN);
    io->ad.smtp.state = SMTP_RDY;
  }
  resp->need = 6 + p - resp->m;  /* Prime the pump for next response */
  return 0;
  
 bad:
  D("SMTP server sent bad response(%.*s)", n, p);
  if (io->pair)
    hmtp_send(hit, io->pair, resp->need, resp->m, 0, 0);
  return HI_CONN_CLOSE;
}
Пример #11
0
Файл: smtp.c Проект: gitpan/zxid
/* Called by:  smtp_decode_resp */
static int smtp_resp_wait_354_from_data(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* resp)
{
  char* p = resp->scan;
  char* lim = resp->ap;
  int next_state, n = lim - p;
  
  if (n < 6) {  /* 250 m\n or 250-m\n */
    resp->need = (6 - n) + (p - resp->m);  /* what we have plus what we need */
    return 0;
  }
  
  if        (THREE_IN_ROW(p, '3', '5', '4')) {  /* 354 enter mail */
    next_state = SMTP_SENT;
  } else if (THREE_IN_ROW(p, '2', '5', '0')) {
    next_state = io->ad.smtp.state;
  } else
    goto bad;
  
  switch (n = p[3]) {
  case ' ':
  case '-':
    for (p+=4; p < lim && !ONE_OF_2(*p, '\r', '\n'); ++p) ;
    CRLF_CHECK(p, lim, resp);
    resp->scan = p;
    break;
  default: goto bad;
  }
  if (n == ' ' && next_state == SMTP_SENT) {
    if (io->ad.smtp.uni_ind_hmtp) {
      /* Send payload immediately */
      /* io->ad.smtp.uni_ind_hmtp is the sis unidata_ind primitive contaning HMTP request */
      char* payload;
      char* q = io->ad.smtp.uni_ind_hmtp->scan;
      char* qlim = io->ad.smtp.uni_ind_hmtp->ap;
      struct hi_pdu* pdu = hi_pdu_alloc(hit, "smtp_wait_354");
      
      payload = q;
      --q;  /* Take the new line from preceding DATA to avoid special case later */
      
      /* Make sure QUIT is NOT sent (we will send one ourselves, eventually). Scan for message
       * terminating "\r\n.\r\n". Its also possible we will not see message terminator. That
       * means the message is so big it takes several SIS primitives to transmit. */
      
      for (; q+2 < qlim; ++q) {
	if (q[0] == '\n' && q[1] == '.' && ONE_OF_2(q[2], '\r', '\n')) {
	  if (q[2] == '\r' && ((q+3 >= qlim) || q[3] != '\n'))
	    continue;
	  q += (q[2] == '\r') ? 4 : 3;
	  break;
	}
      }
      
      D("354 for DATA seen resp(%p), sending %d bytes", resp, (int)(q-payload));
      hi_send1(hit, io, 0, 0, pdu, q-payload, payload);
      io->ad.smtp.state = SMTP_SENT;
      /* *** if hmtp / smtp message was not complete, arrange further SIS layer
       *     I/O to be forwarded into the smtp connection. Similarily, if the
       *     hmtp message has not arrived yet at all, it should be forwarded
       *     as soon as it does arrive. */
    } else {
      NEVER("smtp client io is missing is unidata_ind_hmtp? %p", io->pair);
      return HI_CONN_CLOSE;
    }
  }
  resp->need = 6 + p - resp->m;  /* Prime the pump for next response */
  return 0;
  
 bad:
  D("SMTP server sent bad response(%.*s)", n, p);
  if (io->pair)
    hmtp_send(hit, io->pair, resp->need, resp->m, 0, 0);
  return HI_CONN_CLOSE;
 badhmtp:
  D("Bad HMTP PDU from SIS layer %d", 0);
  if (io->pair)
    hmtp_send(hit, io->pair, 9, "500 Bad\r\n", 0, 0);
  return HI_CONN_CLOSE;
}
Пример #12
0
Файл: smtp.c Проект: gitpan/zxid
/* Called by:  smtp_decode_resp */
static int smtp_resp_wait_250_from_ehlo(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* resp)
{
  char* p = resp->scan;
  char* lim = resp->ap;
  int n = lim - p;
  
  if (n < 6) {  /* 250 m\n or 250-m\n */
    resp->need = (6 - n) + (p - resp->m);  /* what we have plus what we need */
    return 0;
  }
  
  if (!THREE_IN_ROW(p, '2', '5', '0'))
    goto bad;
  
  switch (n = p[3]) {
  case ' ':
  case '-':
    for (p+=4; p < lim && !ONE_OF_2(*p, '\r', '\n'); ++p) ;
    CRLF_CHECK(p, lim, resp);
    resp->scan = p;
    break;
  default: goto bad;
  }
  if (n == ' ') {
    if (io->ad.smtp.uni_ind_hmtp) {
      /* Send payload immediately */
      /* io->ad.smtp.uni_ind_hmtp is the sis unidata_ind primitive contaning HMTP request */
      char* payload;
      char* q = io->ad.smtp.uni_ind_hmtp->scan;
      char* qlim = io->ad.smtp.uni_ind_hmtp->ap;
      struct hi_pdu* pdu = hi_pdu_alloc(hit, "smtp_wait_250");
      
      if (qlim-q < 25)   /* *** should determine this number better */
	goto badhmtp;
      
      /* Skip EHLO if any */
      
      q[0] = toupper(q[0]);
      q[1] = toupper(q[1]);
      q[2] = toupper(q[2]);
      q[3] = toupper(q[3]);
      
      if (memcmp(q, "EHLO ", 5))
	goto badhmtp;

      for (q+=5; q < qlim && !ONE_OF_2(*q, '\r', '\n'); ++q) ;
      if (q == qlim)
	goto badhmtp;
      if (*q == '\r') {
	++q;
	if (q == qlim || *q != '\n')
	  goto badhmtp;
      }
      ++q;
      if (q == qlim)
	goto badhmtp;	
      
      payload = q;
      
      /* Scan till end of DATA command. We can not send the actual data before 354 response
       * to DATA command, for which we wait in SEND state. */

      for (; q+6 < qlim; ++q) {
	if (q[0] == '\n'
	    && ONE_OF_2(q[1], 'D', 'd')
	    && ONE_OF_2(q[2], 'A', 'a')
	    && ONE_OF_2(q[3], 'T', 't')
	    && ONE_OF_2(q[4], 'A', 'a')
	    && ONE_OF_2(q[5], '\r', '\n')
	    ) {
	  if (q[5] == '\r' && ((q+7 >= qlim) || q[6] != '\n'))
	    continue;
	  q += (q[5] == '\r') ? 7 : 6;
	  break;
	}
      }
      
      D("250 for EHLO seen resp(%p)", resp);
      io->ad.smtp.uni_ind_hmtp->scan = q;
      hi_send1(hit, io, 0, 0, pdu, q-payload, payload);
      io->ad.smtp.state = SMTP_SEND;
      /* *** if hmtp / smtp message was not complete, arrange further SIS layer
       *     I/O to be forwarded into the smtp connection. Similarily, if the
       *     hmtp message has not arrived yet at all, it should be forwarded
       *     as soon as it does arrive. */
    } else {
      NEVER("smtp client io is missing is unidata_ind_hmtp? %p", io->pair);
      return HI_CONN_CLOSE;
    }
  }
  resp->need = 6 + p - resp->m;  /* Prime the pump for next response */
  return 0;
  
 bad:
  D("SMTP server sent bad response(%.*s)", n, p);
  if (io->pair)
    hmtp_send(hit, io->pair, resp->need, resp->m, 0, 0);
  return HI_CONN_CLOSE;
 badhmtp:
  D("Bad HMTP PDU from SIS layer %d", 0);
  if (io->pair)
    hmtp_send(hit, io->pair, 9, "500 Bad\r\n", 0, 0);
  return HI_CONN_CLOSE;
}
Пример #13
0
/* Called by: */
int zxumacall_main(int argc, char** argv, char** env)
{
  int siz, got, n;
  char* p;
  struct zx_str* ss;
  zxid_ses* ses;
  zxid_entity* idp_meta;
  zxid_epr* epr;

  strncpy(errmac_instance, CC_CYNY("\tzxuma"), sizeof(errmac_instance));
  cf = zxid_new_conf_to_cf(0);
  opt(&argc, &argv, &env);

  if (dynclireg) {
    zxumacall_dynclireg_client(cf);
    return 0;
  }

  if (rsrc_name) {
    if (!client_secret)
      zxumacall_dynclireg_client(cf);
    zxumacall_rsrcreg_client(cf);
    return 0;
  }
    
  if (sid) {
    D("Existing session sesid(%s)", sid);
    ses = zxid_fetch_ses(cf, sid);
    if (!ses) {
      ERR("Session not found or error in session sesid(%s)", sid);
      return 1;
    }
  } else {
    D("Obtain session from authentication service(%s)", idp);
    idp_meta = zxid_get_ent(cf, idp);
    if (!idp_meta) {
      ERR("IdP metadata not found and could not be fetched. idp(%s)", idp);
      return 1;
    }
    for (p = user; !ONE_OF_2(*p, ':', 0); ++p) ;
    if (*p)
      *p++ = 0;
    ses = zxid_as_call(cf, idp_meta, user, p);
    if (!ses) {
      ERR("Login using Authentication Service failed idp(%s)", idp);
      return 1;
    }
    INFO("Logged in. NameID(%s) Session in %s" ZXID_SES_DIR "%s", ses->nid, cf->cpath, ses->sid);
  }

  if (listses)
    return zxid_print_session(cf, ses);   

  if (im_to) {
    D("ID-WSF Map to identity at eid(%s)", im_to);
    zxid_map_identity_token(cf, ses, im_to, 0);
    //printf("%.*s\n", ZX_GET_CONTENT_LEN(nameid), ZX_GET_CONTENT_S(nameid));
    return 0;
  }

  if (nidmap_to) {
    D("SAML Map to identity at eid(%s)", nidmap_to);
    zxid_nidmap_identity_token(cf, ses, nidmap_to, 0);
    //printf("%.*s\n", ZX_GET_CONTENT_LEN(nameid), ZX_GET_CONTENT_S(nameid));
    return 0;
  }

  if (di_only) {
    D("Discover only. svctype(%s), dindex=%d", STRNULLCHK(svc), din);
    epr = zxid_get_epr(cf, ses, svc, url, di, 0 /*action*/, din);
    if (!epr) {
      ERR("Discovery failed to find any epr of service type(%s)", STRNULLCHK(svc));
      return 3;
    }
    for (din = 1; ;++din) {
      epr = zxid_get_epr(cf, ses, svc, url, di, 0 /*action*/, din);
      if (!epr)
	break;
      printf("%d. Found epr for service type(%s)\n", din, STRNULLCHK(svc));
      ss = zxid_get_epr_desc(cf, epr);
      printf("   Description: %.*s\n", ss?ss->len:0, ss?ss->s:"");
      ss = zxid_get_epr_address(cf, epr);
      printf("   EPURL:       %.*s\n", ss?ss->len:0, ss?ss->s:"");
      ss = zxid_get_epr_entid(cf, epr);
      printf("   EntityID:    %.*s\n", ss?ss->len:0, ss?ss->s:"");
    }
    return 0;
  }
  
  if (svc) {
    D("Call service svctype(%s)", svc);
    if (!bdy) {
      if (verbose)
	fprintf(stderr, "Reading SOAP request body from stdin...\n");
      siz = 4096;
      p = bdy = ZX_ALLOC(cf->ctx, siz);
      while (1) {
	n = read_all_fd(fdstdin, p, siz+bdy-p-1, &got);
	if (n == -1) {
	  perror("reading SOAP req from stdin");
	  break;
	}
	p += got;
	if (got < siz+bdy-p-1) break;
	siz += 60*1024;
	REALLOCN(bdy, siz);
      }
      *p = 0;
    }
    if (dryrun) {
      if (verbose)
	fprintf(stderr, "Dryrun. Call aborted.\n");
      return 0;
    }
    if (verbose)
      fprintf(stderr, "Calling...\n");
    
    ss = zxid_call(cf, ses, svc, url, di, az, bdy);
    if (!ss || !ss->s) {
      ERR("Call failed %p", ss);
      return 2;
    }
    if (verbose)
      fprintf(stderr, "Done. Call returned %d bytes.\n", ss->len);
    if (out_fmt) {
      p = zxid_extract_body(cf, ss->s);
      printf("%s", p);
    } else
      printf("%.*s", ss->len, ss->s);
  } else if (az) {
    D("Call Az(%s)", az);
    if (dryrun) {
      if (verbose)
	fprintf(stderr, "Dryrun. zxid_az() aborted.\n");
      return 0;
    }
    if (zxid_az_cf_ses(cf, az, ses)) {
      if (verbose)
	fprintf(stderr, "Permit.\n");
      return 0;
    } else {
      if (verbose)
	fprintf(stderr, "Deny.\n");
      return 1;
    }
  } else {
    D("Neither service type (-t) nor -az supplied. Performed only authentication. %d",0);
    if (verbose)
      fprintf(stderr, "Authentication only.\n");
  }
  return 0;
}