Ejemplo n.º 1
0
static int do_indexfrom(const char *fromfile)
{
    int r;
    FILE *fp;
    unsigned lineno = 0;
    const char *p;
    tok_t tok;
    const char *mboxname;
    uint32_t uid;
    char buf[MAX_MAILBOX_BUFFER+128];

    rx = search_begin_update(verbose);
    if (rx == NULL) /* no indexer defined */
        return 0;

    fp = fopen(fromfile, "r");
    if (!fp) {
        r = errno;
        perror(fromfile);
        goto out;
    }

    while (fgets(buf, sizeof(buf), fp)) {
        lineno++;
        if (buf[0] == '#') continue;
        tok_initm(&tok, buf, "\t", TOK_EMPTY|TOK_TRIMRIGHT);

        /* first token is an mboxname */
        mboxname = tok_next(&tok);
        if (!mboxname) {
syntax_error:
            fprintf(stderr, "%s:%u: syntax error, skipping\n",
                    fromfile, lineno);
            continue;
        }

        /* 2nd token is a uid */
        p = tok_next(&tok);
        if (!p) goto syntax_error;
        uid = strtoul(p, NULL, 0);
        if (!uid) goto syntax_error;

        /* no more tokens on the line */
        p = tok_next(&tok);
        if (p) goto syntax_error;

        r = index_single_message(mboxname, uid);
        if (r) {
            fprintf(stderr, "Failed to index mailbox \"%s\" uid %u: %s\n",
                    mboxname, uid, error_message(r));
            /* ignore errors */
            r = 0;
        }
    }

out:
    if (fp) fclose(fp);
    search_end_update(rx);
    return r;
}
Ejemplo n.º 2
0
/*
 * Add iCalendar recur-rule-parts to a structured element.
 */
void icalrecurrencetype_add_as_xxx(struct icalrecurrencetype *recur, void *obj,
                                   void (*add_int)(void *, const char *, int),
                                   void (*add_str)(void *, const char *,
                                           const char *))
{
    char *rrule, *rpart;
    tok_t rparts;

    /* generate an iCal RRULE string */
    rrule = icalrecurrencetype_as_string_r(recur);

    /* split string into rparts & values */
    tok_initm(&rparts, rrule, "=;", TOK_TRIMLEFT|TOK_TRIMRIGHT);
    while ((rpart = tok_next(&rparts))) {
        if (!strcmp(rpart, "UNTIL")) {
            /* need to translate date format to ISO */
            struct icaltimetype until = icaltime_from_string(tok_next(&rparts));

            add_str(obj, "until", icaltime_as_iso_string(until));
        }
        else {
            /* assume the rpart has multiple values - split them */
            tok_t vlist;
            char *val, *p;

            tok_init(&vlist, tok_next(&rparts), ",",
                     TOK_TRIMLEFT|TOK_TRIMRIGHT);
            while ((val = tok_next(&vlist))) {
                if (add_int) {
                    /* try converting value to integer */
                    int n = strtol(val, &p, 10);

                    if (n && !*p) {
                        add_int(obj, lcase(rpart), n);
                        continue;
                    }
                }

                add_str(obj, lcase(rpart), val);
            }
            tok_fini(&vlist);
        }
    }
    tok_fini(&rparts);

    free(rrule);
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
EXPORTED void tok_init(tok_t *t, const char *str, const char *sep, int flags)
{
    tok_initm(t, str ? xstrdup(str) : NULL, sep, flags|TOK_FREEBUFFER);
}
Ejemplo n.º 5
0
EXPORTED struct backend *backend_connect(struct backend *ret_backend, const char *server,
				struct protocol_t *prot, const char *userid,
				sasl_callback_t *cb, const char **auth_status,
				int logfd)

{
    /* need to (re)establish connection to server or create one */
    int sock = -1;
    int r;
    int err = -1;
    int do_tls = 0;
    int noauth = 0;
    struct addrinfo hints, *res0 = NULL, *res;
    struct sockaddr_un sunsock;
    struct backend *ret;

    if (!ret_backend) {
	ret = xzmalloc(sizeof(struct backend));
	strlcpy(ret->hostname, server, sizeof(ret->hostname));
	ret->timeout = NULL;
    }
    else
	ret = ret_backend;

    if (server[0] == '/') { /* unix socket */
	res0 = &hints;
	memset(res0, 0, sizeof(struct addrinfo));
	res0->ai_family = PF_UNIX;
	res0->ai_socktype = SOCK_STREAM;

	res0->ai_addr = (struct sockaddr *) &sunsock;
	res0->ai_addrlen = sizeof(sunsock.sun_family) + strlen(server) + 1;
#ifdef SIN6_LEN
	res0->ai_addrlen += sizeof(sunsock.sun_len);
	sunsock.sun_len = res0->ai_addrlen;
#endif
	sunsock.sun_family = AF_UNIX;
	strlcpy(sunsock.sun_path, server, sizeof(sunsock.sun_path));

	if (!strcmp(prot->sasl_service, "lmtp") ||
	    !strcmp(prot->sasl_service, "csync")) {
	    noauth = 1;
	}
    }
    else { /* inet socket */
	char host[1024], *p;
	const char *service = prot->service;

	/* Parse server string for possible port and options */
	strlcpy(host, server, sizeof(host));
	if ((p = strchr(host, ':'))) {
	    *p++ = '\0';
	    service = p;

	    if ((p = strchr(service, '/'))) {
		tok_t tok;
		char *opt;

		*p++ = '\0';
		tok_initm(&tok, p, "/", 0);
		while ((opt = tok_next(&tok))) {
		    if (!strcmp(opt, "tls")) do_tls = 1;
		    else if (!strcmp(opt, "noauth")) noauth = 1;
		}
		tok_fini(&tok);
	    }
	}

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	err = getaddrinfo(host, service, &hints, &res0);
	if (err) {
	    syslog(LOG_ERR, "getaddrinfo(%s) failed: %s",
		   server, gai_strerror(err));
	    goto error;
	}
    }

    for (res = res0; res; res = res->ai_next) {
	sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (sock < 0)
	    continue;

	/* Do a non-blocking connect() */
	nonblock(sock, 1);
	if (!connect(sock, res->ai_addr, res->ai_addrlen)) {
	    /* connect() succeeded immediately */
	    break;
	}
	else if (errno == EINPROGRESS) {
	    /* connect() in progress */
	    int n;
	    fd_set wfds, rfds;
	    time_t now = time(NULL);
	    time_t timeout = now + config_getint(IMAPOPT_CLIENT_TIMEOUT);
	    struct timeval waitfor;

	    /* select() socket for writing until we succeed, fail, or timeout */
	    do {
		FD_ZERO(&wfds);
		FD_SET(sock, &wfds);
		rfds = wfds;
		waitfor.tv_sec = timeout - now;
		waitfor.tv_usec = 0;

		n = select(sock + 1, &rfds, &wfds, NULL, &waitfor);
		now = time(NULL);

		/* Retry select() if interrupted */
	    } while (n < 0 && errno == EINTR && now < timeout);

	    if (!n) {
		/* select() timed out */
		errno = ETIMEDOUT;
	    }
	    else if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &wfds)) {
		/* Socket is ready for I/O - get SO_ERROR to determine status */
		socklen_t errlen = sizeof(err);

		if (!getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen) &&
		    !(errno = err)) {
		    /* connect() succeeded */
		    break;
		}
	    }
	}

	close(sock);
	sock = -1;
    }

    if (sock < 0) {
	if (res0 != &hints) freeaddrinfo(res0);
	syslog(LOG_ERR, "connect(%s) failed: %m", server);
	goto error;
    }

    /* Reset socket to blocking */
    nonblock(sock, 0);

    memcpy(&ret->addr, res->ai_addr, res->ai_addrlen);
    if (res0 != &hints)
	freeaddrinfo(res0);

    ret->in = prot_new(sock, 0);
    ret->out = prot_new(sock, 1);
    ret->sock = sock;
    prot_settimeout(ret->in, config_getint(IMAPOPT_CLIENT_TIMEOUT));
    prot_setflushonread(ret->in, ret->out);
    ret->prot = prot;

    /* use literal+ to send literals */
    prot_setisclient(ret->in, 1);
    prot_setisclient(ret->out, 1);

    /* Start TLS if required */
    if (do_tls) r = backend_starttls(ret, NULL, NULL, NULL);

    /* Login to the server */
    if (prot->type == TYPE_SPEC)
	r = prot->u.spec.login(ret, userid, cb, auth_status, noauth);
    else
	r = backend_login(ret, userid, cb, auth_status, noauth);

    if (r) goto error;

    if (logfd >= 0) {
	prot_setlog(ret->in, logfd);
	prot_setlog(ret->out, logfd);
    }
    else prot_settimeout(ret->in, 0);

    return ret;

error:
    forget_capabilities(ret);
    if (ret->in) {
	prot_free(ret->in);
	ret->in = NULL;
    }
    if (ret->out) {
	prot_free(ret->out);
	ret->out = NULL;
    }
    if (sock >= 0)
	close(sock);
    if (ret->saslconn) {
	sasl_dispose(&ret->saslconn);
	ret->saslconn = NULL;
    }
    if (!ret_backend)
	free(ret);
    return NULL;
}
Ejemplo n.º 6
0
/* Parse Sec-WebSocket-Extensions header(s) for interesting extensions */
static void parse_extensions(struct transaction_t *txn)
{
    struct ws_context *ctx = (struct ws_context *) txn->ws_ctx;
    const char **ext_hdr =
        spool_getheader(txn->req_hdrs, "Sec-WebSocket-Extensions");
    int i;

    /* Look for interesting extensions.  Unknown == ignore */
    for (i = 0; ext_hdr && ext_hdr[i]; i++) {
        tok_t ext = TOK_INITIALIZER(ext_hdr[i], ",", TOK_TRIMLEFT|TOK_TRIMRIGHT);
        char *token;

        while ((token = tok_next(&ext))) {
            struct ws_extension *extp = extensions;
            tok_t param;

            tok_initm(&param, token, ";", TOK_TRIMLEFT|TOK_TRIMRIGHT);
            token = tok_next(&param);

            /* Locate a matching extension */
            while (extp->name && strcmp(token, extp->name)) extp++;

            /* Check if client wants per-message compression */
            if (extp->flag == EXT_PMCE_DEFLATE) {
                unsigned client_max_wbits = MAX_WBITS;

                ctx->pmce.deflate.max_wbits = MAX_WBITS;

                /* Process parameters */
                while ((token = tok_next(&param))) {
                    char *value = strchr(token, '=');

                    if (value) *value++ = '\0';

                    if (!strcmp(token, "server_no_context_takeover")) {
                        ctx->pmce.deflate.no_context = 1;
                    }
                    else if (!strcmp(token, "client_no_context_takeover")) {
                        /* Don't HAVE to do anything here */
                    }
                    else if (!strcmp(token, "server_max_window_bits")) {
                        if (value) {
                            if (*value == '"') value++;
                            ctx->pmce.deflate.max_wbits = atoi(value);
                        }
                        else ctx->pmce.deflate.max_wbits = 0;  /* force error */
                    }
                    else if (!strcmp(token, "client_max_window_bits")) {
                        if (value) {
                            if (*value == '"') value++;
                            client_max_wbits = atoi(value);
                        }
                    }
                }
#ifdef HAVE_ZLIB
                /* Reconfigure compression context for raw deflate */
                if (txn->zstrm) deflateEnd(txn->zstrm);
                else txn->zstrm = xmalloc(sizeof(z_stream));

                if (deflateInit2(txn->zstrm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
                                 -ctx->pmce.deflate.max_wbits,
                                 MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
                    free(txn->zstrm);
                    txn->zstrm = NULL;
                }
                if (txn->zstrm) {
                    /* Configure decompression context for raw deflate */
                    ctx->pmce.deflate.zstrm = xmalloc(sizeof(z_stream));
                    if (inflateInit2(ctx->pmce.deflate.zstrm,
                                     -client_max_wbits) != Z_OK) {
                        free(ctx->pmce.deflate.zstrm);
                        ctx->pmce.deflate.zstrm = NULL;
                    }
                }
#endif /* HAVE_ZLIB */
                if (ctx->pmce.deflate.zstrm) {
                    /* Compression has been enabled */
                    wslay_event_config_set_allowed_rsv_bits(ctx->event,
                                                            WSLAY_RSV1_BIT);
                    ctx->ext = extp->flag;
                }
            }

            tok_fini(&param);
        }

        tok_fini(&ext);
    }
}