Пример #1
0
static int make_key(struct buf *key, const duplicate_key_t *dkey)
{
    if (!dkey ||
        !dkey->id ||
	!dkey->to ||
	!dkey->date)
	return IMAP_INTERNAL;

    buf_reset(key);
    buf_appendmap(key, dkey->id, strlen(dkey->id)+1);
    buf_appendmap(key, dkey->to, strlen(dkey->to)+1);
    buf_appendmap(key, dkey->date, strlen(dkey->date)+1);
    /* We have three concatenated values now, all parts ending with '\0' */

    return 0;
}
Пример #2
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;
}
Пример #3
0
EXPORTED char *jmapauth_tokenid(const struct jmapauth_token *tok)
{
    struct buf buf = BUF_INITIALIZER;
    unsigned mdlen, hexlen;
    char macbuf[EVP_MAX_MD_SIZE];
    char hexbuf[(JMAPAUTH_KEY_LEN + EVP_MAX_MD_SIZE)*2];
    int r;

    /* Build the key */
    r = make_key(&buf, tok);
    if (r) return NULL;

    /* Sign the extended key */
    if (!(HMAC(EVP_sha1(), tok->secret, JMAPAUTH_SECRET_LEN,
               (unsigned char*) buf.s, buf.len,
               (unsigned char*) macbuf, &mdlen))) {
        buf_free(&buf);
        return NULL;
    }
    buf_appendmap(&buf, macbuf, mdlen);

    /* And return it hex-encoded */
    hexlen = bin_to_hex(buf.s, buf.len, hexbuf, 0);
    if (hexlen != (mdlen + JMAPAUTH_KEY_LEN)*2) {
        buf_free(&buf);
        return NULL;
    }

    buf_free(&buf);
    return xstrndup(hexbuf, hexlen);
}
Пример #4
0
static int make_key(struct buf *buf, const struct jmapauth_token *tok)
{
    /* Concatenate version, kind and the session id */
    buf_putc(buf, tok->version);
    buf_putc(buf, tok->kind);
    buf_appendmap(buf, tok->sessionid, JMAPAUTH_SESSIONID_LEN);
    return 0;
}
Пример #5
0
static int _parseitem(struct dlistsax_state *s, struct buf *buf)
{
    const char *sp;
    if (*s->p == '"')
        return _parseqstring(s, buf);
    else if (*s->p == '{')
        return _parseliteral(s, buf);

    sp = memchr(s->p, ' ', s->end - s->p);
    if (!sp) sp = s->end;
    while (sp[-1] == ')' && sp > s->p) sp--;
    /* this is much faster because it doesn't do a reset and check the MMAP flag */
    buf->len = 0;
    buf_appendmap(buf, s->p, sp - s->p);
    s->p = sp;
    return 0; /* this could be the last thing, so end is OK */
}
Пример #6
0
static int build_notify_message(sieve_interp_t *i,
                                const char *msg,
                                void *message_context,
                                struct buf *out)
{
    const char *c;
    size_t n;

    if (msg == NULL) return SIEVE_OK;

    /* construct the message */
    c = msg;
    while (*c) {
        /* expand variables */
        if (!strncasecmp(c, "$from$", 6)) {
            add_header(i, 0 ,"From", message_context, out);
            c += 6;
        }
        else if (!strncasecmp(c, "$env-from$", 10)) {
            add_header(i, 1, "From", message_context, out);
            c += 10;
        }
        else if (!strncasecmp(c, "$subject$", 9)) {
            add_header(i, 0, "Subject", message_context, out);
            c += 9;
        }
        else if (i->getbody &&
                 !strncasecmp(c, "$text", 5) && (c[5] == '[' || c[5] == '$')) {
            const char *content_types[] = { "text", NULL };
            sieve_bodypart_t **parts = NULL;

            c += 5;
            n = 0;
            if (*c++ == '[') {
                while (*c != ']') n = n * 10 + (*c++ - '0');
                c += 2; /* skip ]$ */
            }

            i->getbody(message_context, content_types, &parts);

            /* we only use the first text part */
            if (parts && parts[0] && parts[0]->decoded_body) {
                size_t size = strlen(parts[0]->decoded_body);
                if (n && size > n) size = n;
                buf_appendmap(out, parts[0]->decoded_body, size);
            }

            /* free the results */
            if (parts) {
                sieve_bodypart_t **p;

                for (p = parts; *p; p++) free(*p);
                free(parts);
            }
        }
        else {
            /* find length of plaintext up to next potential variable */
            n = strcspn(c+1, "$") + 1; /* skip opening '$' */
            buf_appendmap(out, c, n);
            c += n;
        }
    }

    buf_cstring(out);
    return SIEVE_OK;
}
Пример #7
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);
}