예제 #1
0
파일: sendto_kdc.c 프로젝트: Akasurde/krb5
/* Set conn->state to READING when done; otherwise, call a cm_set_. */
static krb5_boolean
service_https_write(krb5_context context, const krb5_data *realm,
                    struct conn_state *conn, struct select_state *selstate)
{
    k5_tls_status st;

    /* If this is our first time in here, set up the SSL context. */
    if (conn->http.tls == NULL && !setup_tls(context, realm, conn, selstate)) {
        kill_conn(context, conn, selstate);
        return FALSE;
    }

    /* Try to transmit our request to the server. */
    st = context->tls->write(context, conn->http.tls, SG_BUF(conn->out.sgp),
                             SG_LEN(conn->out.sgbuf));
    if (st == DONE) {
        TRACE_SENDTO_KDC_HTTPS_SEND(context, &conn->addr);
        cm_read(selstate, conn->fd);
        conn->state = READING;
    } else if (st == WANT_READ) {
        cm_read(selstate, conn->fd);
    } else if (st == WANT_WRITE) {
        cm_write(selstate, conn->fd);
    } else if (st == ERROR_TLS) {
        TRACE_SENDTO_KDC_HTTPS_ERROR_SEND(context, &conn->addr);
        kill_conn(context, conn, selstate);
    }

    return FALSE;
}
예제 #2
0
/* Create a new category map from a string that can
    either be a filename or a brief "inlined" category map, e.g.,
    "NCATS = 3 ; CDS 1-3".  Useful for command-line arguments. */
CategoryMap* cm_new_string_or_file(const char *optarg) {
  int i;
  char fname[STR_SHORT_LEN];
  String *str = str_new_charstr(optarg);
  FILE *F;
  CategoryMap *retval = NULL;

  str_double_trim(str);
  if (str_starts_with_charstr(str, "NCATS")) {
    /* replace semicolons with carriage returns */
    for (i = 0; i < str->length; i++)
      if (str->chars[i] == ';') str->chars[i] = '\n';

    /* we'll just dump a little tmp file and read it with cm_read */
    sprintf(fname, "cm.tmp.%d", getpid());
    F = phast_fopen(fname, "w+");
    fprintf(F, "%s", str->chars);
    phast_fclose(F);
    F = phast_fopen(fname, "r");
    retval = cm_read(F);
    phast_fclose(F);
    unlink(fname);
  }
  else {
    F = phast_fopen(str->chars, "r");
    retval = cm_read(F);
    phast_fclose(F);
  }

  str_free(str);
  return retval;
}
예제 #3
0
파일: sendto_kdc.c 프로젝트: Akasurde/krb5
/* Sets conn->state to READING when done. */
static krb5_boolean
service_tcp_write(krb5_context context, const krb5_data *realm,
                  struct conn_state *conn, struct select_state *selstate)
{
    ssize_t nwritten;
    SOCKET_WRITEV_TEMP tmp;

    TRACE_SENDTO_KDC_TCP_SEND(context, &conn->addr);
    nwritten = SOCKET_WRITEV(conn->fd, conn->out.sgp, conn->out.sg_count, tmp);
    if (nwritten < 0) {
        TRACE_SENDTO_KDC_TCP_ERROR_SEND(context, &conn->addr, SOCKET_ERRNO);
        kill_conn(context, conn, selstate);
        return FALSE;
    }
    while (nwritten) {
        sg_buf *sgp = conn->out.sgp;
        if ((size_t)nwritten < SG_LEN(sgp)) {
            SG_ADVANCE(sgp, (size_t)nwritten);
            nwritten = 0;
        } else {
            nwritten -= SG_LEN(sgp);
            conn->out.sgp++;
            conn->out.sg_count--;
        }
    }
    if (conn->out.sg_count == 0) {
        /* Done writing, switch to reading. */
        cm_read(selstate, conn->fd);
        conn->state = READING;
    }
    return FALSE;
}
예제 #4
0
/* simple wrapper for cm_read that opens specified filename and reads
   a category map from it; aborts with error message if unable to open
   the file.  Saves typing in mains for command-line programs */
CategoryMap* cm_read_from_fname(char *fname) {
  CategoryMap *cm = NULL;
  FILE *F;
  F = phast_fopen(fname, "r"); 
  if ((cm = cm_read(F)) == NULL)
    die("ERROR: cannot read category map from %s.\n", fname);
  phast_fclose(F);
  return cm;
}
예제 #5
0
파일: sendto_kdc.c 프로젝트: Akasurde/krb5
/* Return true on finished data.  Call a cm_read/write function and return
 * false if the TLS layer needs it.  Kill the connection on error. */
static krb5_boolean
https_read_bytes(krb5_context context, struct conn_state *conn,
                 struct select_state *selstate)
{
    size_t bufsize, nread;
    k5_tls_status st;
    char *tmp;
    struct incoming_message *in = &conn->in;

    for (;;) {
        if (in->buf == NULL || in->bufsize - in->pos < 1024) {
            bufsize = in->bufsize ? in->bufsize * 2 : 8192;
            if (bufsize > 1024 * 1024) {
                kill_conn(context, conn, selstate);
                return FALSE;
            }
            tmp = realloc(in->buf, bufsize);
            if (tmp == NULL) {
                kill_conn(context, conn, selstate);
                return FALSE;
            }
            in->buf = tmp;
            in->bufsize = bufsize;
        }

        st = context->tls->read(context, conn->http.tls, &in->buf[in->pos],
                                in->bufsize - in->pos - 1, &nread);
        if (st != DATA_READ)
            break;

        in->pos += nread;
        in->buf[in->pos] = '\0';
    }

    if (st == DONE)
        return TRUE;

    if (st == WANT_READ) {
        cm_read(selstate, conn->fd);
    } else if (st == WANT_WRITE) {
        cm_write(selstate, conn->fd);
    } else if (st == ERROR_TLS) {
        TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(context, &conn->addr);
        kill_conn(context, conn, selstate);
    }
    return FALSE;
}
예제 #6
0
파일: sendto_kdc.c 프로젝트: Akasurde/krb5
static int
start_connection(krb5_context context, struct conn_state *state,
                 const krb5_data *message, struct select_state *selstate,
                 const krb5_data *realm,
                 struct sendto_callback_info *callback_info)
{
    int fd, e, type;
    static const int one = 1;
    static const struct linger lopt = { 0, 0 };

    type = socktype_for_transport(state->addr.transport);
    fd = socket(state->addr.family, type, 0);
    if (fd == INVALID_SOCKET)
        return -1;              /* try other hosts */
    set_cloexec_fd(fd);
    /* Make it non-blocking.  */
    ioctlsocket(fd, FIONBIO, (const void *) &one);
    if (state->addr.transport == TCP) {
        setsockopt(fd, SOL_SOCKET, SO_LINGER, &lopt, sizeof(lopt));
        TRACE_SENDTO_KDC_TCP_CONNECT(context, &state->addr);
    }

    /* Start connecting to KDC.  */
    e = connect(fd, (struct sockaddr *)&state->addr.saddr, state->addr.len);
    if (e != 0) {
        /*
         * This is the path that should be followed for non-blocking
         * connections.
         */
        if (SOCKET_ERRNO == EINPROGRESS || SOCKET_ERRNO == EWOULDBLOCK) {
            state->state = CONNECTING;
            state->fd = fd;
        } else {
            (void) closesocket(fd);
            state->state = FAILED;
            return -2;
        }
    } else {
        /*
         * Connect returned zero even though we made it non-blocking.  This
         * happens normally for UDP sockets, and can perhaps also happen for
         * TCP sockets connecting to localhost.
         */
        state->state = WRITING;
        state->fd = fd;
    }

    /*
     * Here's where KPASSWD callback gets the socket information it needs for
     * a kpasswd request
     */
    if (callback_info) {

        e = callback_info->pfn_callback(state->fd, callback_info->data,
                                        &state->callback_buffer);
        if (e != 0) {
            (void) closesocket(fd);
            state->fd = INVALID_SOCKET;
            state->state = FAILED;
            return -3;
        }

        message = &state->callback_buffer;
    }

    e = set_transport_message(state, realm, message);
    if (e != 0) {
        TRACE_SENDTO_KDC_ERROR_SET_MESSAGE(context, &state->addr, e);
        (void) closesocket(state->fd);
        state->fd = INVALID_SOCKET;
        state->state = FAILED;
        return -4;
    }

    if (state->addr.transport == UDP) {
        /* Send it now.  */
        ssize_t ret;
        sg_buf *sg = &state->out.sgbuf[0];

        TRACE_SENDTO_KDC_UDP_SEND_INITIAL(context, &state->addr);
        ret = send(state->fd, SG_BUF(sg), SG_LEN(sg), 0);
        if (ret < 0 || (size_t) ret != SG_LEN(sg)) {
            TRACE_SENDTO_KDC_UDP_ERROR_SEND_INITIAL(context, &state->addr,
                                                    SOCKET_ERRNO);
            (void) closesocket(state->fd);
            state->fd = INVALID_SOCKET;
            state->state = FAILED;
            return -5;
        } else {
            state->state = READING;
        }
    }

    if (!cm_add_fd(selstate, state->fd)) {
        (void) closesocket(state->fd);
        state->fd = INVALID_SOCKET;
        state->state = FAILED;
        return -1;
    }
    if (state->state == CONNECTING || state->state == WRITING)
        cm_write(selstate, state->fd);
    else
        cm_read(selstate, state->fd);

    return 0;
}