Exemplo n.º 1
0
static int denydb_foreach_cb(void *rock,
			     const char *key, size_t keylen,
			     const char *data, size_t datalen)
{
    struct denydb_rock *dr = (struct denydb_rock *)rock;
    struct buf user = BUF_INITIALIZER;
    struct buf buf = BUF_INITIALIZER;
    char *wild = NULL;
    const char *msg = NULL;
    int r;

    /* ensure we have a nul-terminated user string */
    buf_appendmap(&user, key, keylen);
    buf_cstring(&user);

    /* get fields from the record */
    buf_init_ro(&buf, data, datalen);
    r = parse_record(&buf, &wild, &msg);
    if (r) {
	syslog(LOG_WARNING,
	       "DENYDB_ERROR: invalid entry for '%s'", user.s);
	r = 0;	/* whatever, keep going */
	goto out;
    }

    r = dr->proc(user.s, wild, msg, dr->rock);

out:
    buf_free(&user);
    buf_free(&buf);
    return r;
}
Exemplo n.º 2
0
EXPORTED void rfc822tok_init(rfc822tok_t *t, const char *base,
                             unsigned int len, unsigned int flags)
{
    buf_init_ro(&t->buf, base, len);
    t->ptr = base;
    t->flags = flags;
}
Exemplo n.º 3
0
EXPORTED int dlist_getbuf(struct dlist *parent, const char *name,
                          struct buf *value)
{
    const char *v = NULL;
    size_t l = 0;
    if (dlist_getmap(parent, name, &v, &l)) {
        buf_init_ro(value, v, l);
        return 1;
    }
    return 0;
}
Exemplo n.º 4
0
/*
 * userdeny() checks to see if 'user' is denied access to 'service'
 * Returns 1 if a matching deny entry exists in DB, otherwise returns 0.
 */
EXPORTED int userdeny(const char *user, const char *service, char *msgbuf, size_t bufsiz)
{
    int r, ret = 0; /* allow access by default */
    const char *data = NULL;
    size_t datalen;
    struct buf buf = BUF_INITIALIZER;
    char *wild = NULL;
    const char *msg = NULL;
    tok_t tok;
    char *pat;
    int not;

    if (!denydb) denydb_open(/*create*/0);
    if (!denydb) return 0;

    memset(&tok, 0, sizeof(tok));

    /* fetch entry for user */
    syslog(LOG_DEBUG, "fetching user_deny.db entry for '%s'", user);
    do {
	r = cyrusdb_fetch(denydb, user, strlen(user), &data, &datalen, NULL);
    } while (r == CYRUSDB_AGAIN);

    /* XXX  Should we try to reopen the DB if we get IOERROR?
	    This might be necessary when using SQL backend
	    and we lose the connection.
    */

    if (r || !data || !datalen) {
	/* ignore non-existent/empty entry, report all other errors */
	if (r != CYRUSDB_NOTFOUND) {
	    syslog(LOG_WARNING,
		   "DENYDB_ERROR: error reading entry '%s': %s",
		   user, cyrusdb_strerror(r));
	}
	goto out;
    }
    buf_init_ro(&buf, data, datalen);

	/* parse the data */
    r = parse_record(&buf, &wild, &msg);
    if (r) {
	syslog(LOG_WARNING,
	       "DENYDB_ERROR: invalid entry for '%s'", user);
	goto out;
    }

    /* scan wildmat right to left for a match against our service */
    syslog(LOG_DEBUG, "wild: '%s'   service: '%s'", wild, service);
    tok_initm(&tok, wild, ",", 0);
    while ((pat = tok_next(&tok))) {
	/* XXX  trim leading & trailing whitespace? */

	/* is it a negated pattern? */
	not = (*pat == '!');
	if (not) ++pat;

	syslog(LOG_DEBUG, "pat %d:'%s'", not, pat);

	/* see if pattern matches our service */
	if (wildmat(service, pat)) {
	    /* match ==> we're done */
	    ret = !not;
	    if (msgbuf) strlcpy(msgbuf, msg, bufsiz);
	    break;
	}
    }

out:
    tok_fini(&tok);
    buf_free(&buf);
    return ret;
}
Exemplo n.º 5
0
static void on_msg_recv_cb(wslay_event_context_ptr ev,
                           const struct wslay_event_on_msg_recv_arg *arg,
                           void *user_data)
{
    struct transaction_t *txn = (struct transaction_t *) user_data;
    struct ws_context *ctx = (struct ws_context *) txn->ws_ctx;
    struct buf inbuf = BUF_INITIALIZER, outbuf = BUF_INITIALIZER;
    struct wslay_event_msg msgarg = { arg->opcode, NULL, 0 };
    uint8_t rsv = WSLAY_RSV_NONE;
    double cmdtime, nettime;
    const char *err_msg;
    int r, err_code = 0;

    /* Place client request into a buf */
    buf_init_ro(&inbuf, (const char *) arg->msg, arg->msg_length);

    /* Decompress request, if necessary */
    if (wslay_get_rsv1(arg->rsv)) {
        /* Add trailing 4 bytes */
        buf_appendmap(&inbuf, "\x00\x00\xff\xff", 4);

        r = zlib_decompress(txn, buf_base(&inbuf), buf_len(&inbuf));
        if (r) {
            syslog(LOG_ERR, "on_msg_recv_cb(): zlib_decompress() failed");

            err_code = WSLAY_CODE_PROTOCOL_ERROR;
            err_msg = DECOMP_FAILED_ERR;
            goto err;
        }

        buf_move(&inbuf, &txn->zbuf);
    }

    /* Log the uncompressed client request */
    buf_truncate(&ctx->log, ctx->log_tail);
    buf_appendcstr(&ctx->log, " (");
    if (txn->strm_ctx) {
        buf_printf(&ctx->log, "stream-id=%d; ",
                   http2_get_streamid(txn->strm_ctx));
    }
    buf_printf(&ctx->log, "opcode=%s; rsv=0x%x; length=%ld",
               wslay_str_opcode(arg->opcode), arg->rsv, arg->msg_length);

    switch (arg->opcode) {
    case WSLAY_CONNECTION_CLOSE:
        buf_printf(&ctx->log, "; status=%d; msg='%s'", arg->status_code,
                   buf_len(&inbuf) ? buf_cstring(&inbuf)+2 : "");
        txn->flags.conn = CONN_CLOSE;
        break;

    case WSLAY_TEXT_FRAME:
    case WSLAY_BINARY_FRAME:
        if (txn->conn->logfd != -1) {
            /* Telemetry logging */
            struct iovec iov[2];
            int niov = 0;

            assert(!buf_len(&txn->buf));
            buf_printf(&txn->buf, "<%ld<", time(NULL));  /* timestamp */
            WRITEV_ADD_TO_IOVEC(iov, niov,
                                buf_base(&txn->buf), buf_len(&txn->buf));
            WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&inbuf), buf_len(&inbuf));
            writev(txn->conn->logfd, iov, niov);
            buf_reset(&txn->buf);
        }

        /* Process the request */
        r = ctx->data_cb(&inbuf, &outbuf, &ctx->log, &ctx->cb_rock);
        if (r) {

            err_code = (r == HTTP_SERVER_ERROR ?
                        WSLAY_CODE_INTERNAL_SERVER_ERROR :
                        WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA);
            err_msg = error_message(r);
            goto err;
        }

        if (txn->conn->logfd != -1) {
            /* Telemetry logging */
            struct iovec iov[2];
            int niov = 0;

            assert(!buf_len(&txn->buf));
            buf_printf(&txn->buf, ">%ld>", time(NULL));  /* timestamp */
            WRITEV_ADD_TO_IOVEC(iov, niov,
                                buf_base(&txn->buf), buf_len(&txn->buf));
            WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&outbuf), buf_len(&outbuf));
            writev(txn->conn->logfd, iov, niov);
            buf_reset(&txn->buf);
        }

        /* Compress the server response, if supported by the client */
        if (ctx->ext & EXT_PMCE_DEFLATE) {
            r = zlib_compress(txn,
                              ctx->pmce.deflate.no_context ? COMPRESS_START : 0,
                              buf_base(&outbuf), buf_len(&outbuf));
            if (r) {
                syslog(LOG_ERR, "on_msg_recv_cb(): zlib_compress() failed");

                err_code = WSLAY_CODE_INTERNAL_SERVER_ERROR;
                err_msg = COMP_FAILED_ERR;
                goto err;
            }

            /* Trim the trailing 4 bytes */
            buf_truncate(&txn->zbuf, buf_len(&txn->zbuf) - 4);
            buf_move(&outbuf, &txn->zbuf);

            rsv |= WSLAY_RSV1_BIT;
        }

        /* Queue the server response */
        msgarg.msg = (const uint8_t *) buf_base(&outbuf);
        msgarg.msg_length = buf_len(&outbuf);
        wslay_event_queue_msg_ex(ev, &msgarg, rsv);

        /* Log the server response */
        buf_printf(&ctx->log,
                   ") => \"Success\" (opcode=%s; rsv=0x%x; length=%ld",
                   wslay_str_opcode(msgarg.opcode), rsv, msgarg.msg_length);
        break;
    }

  err:
    if (err_code) {
        size_t err_msg_len = strlen(err_msg);

        syslog(LOG_DEBUG, "wslay_event_queue_close()");
        wslay_event_queue_close(ev, err_code, (uint8_t *) err_msg, err_msg_len);

        /* Log the server response */
        buf_printf(&ctx->log,
                   ") => \"Fail\" (opcode=%s; rsv=0x%x; length=%ld"
                   "; status=%d; msg='%s'",
                   wslay_str_opcode(WSLAY_CONNECTION_CLOSE), rsv, err_msg_len,
                   err_code, err_msg);
    }

    /* Add timing stats */
    cmdtime_endtimer(&cmdtime, &nettime);
    buf_printf(&ctx->log, ") [timing: cmd=%f net=%f total=%f]",
               cmdtime, nettime, cmdtime + nettime);

    syslog(LOG_INFO, "%s", buf_cstring(&ctx->log));

    buf_free(&inbuf);
    buf_free(&outbuf);
}