static void client_proxy_create(struct client *client, const struct submission_settings *set) { struct mail_user *user = client->user; struct ssl_iostream_settings ssl_set; struct smtp_client_settings smtp_set; enum smtp_client_connection_ssl_mode ssl_mode; i_zero(&ssl_set); mail_user_init_ssl_client_settings(user, &ssl_set); if (set->submission_relay_ssl_verify) ssl_set.verbose_invalid_cert = TRUE; else ssl_set.allow_invalid_cert = TRUE; /* make proxy connection */ i_zero(&smtp_set); smtp_set.my_hostname = set->hostname; smtp_set.ssl = &ssl_set; smtp_set.debug = user->mail_debug; smtp_set.rawlog_dir = mail_user_home_expand(user, set->submission_relay_rawlog_dir); if (set->submission_relay_trusted) { smtp_set.peer_trusted = TRUE; if (user->conn.remote_ip != NULL) { smtp_set.proxy_data.source_ip = *user->conn.remote_ip; smtp_set.proxy_data.source_port = user->conn.remote_port; } smtp_set.proxy_data.login = user->username; } smtp_set.username = set->submission_relay_user; smtp_set.master_user = set->submission_relay_master_user; smtp_set.password = set->submission_relay_password; smtp_set.connect_timeout_msecs = set->submission_relay_connect_timeout; smtp_set.command_timeout_msecs = set->submission_relay_command_timeout; if (strcmp(set->submission_relay_ssl, "smtps") == 0) ssl_mode = SMTP_CLIENT_SSL_MODE_IMMEDIATE; else if (strcmp(set->submission_relay_ssl, "starttls") == 0) ssl_mode = SMTP_CLIENT_SSL_MODE_STARTTLS; else ssl_mode = SMTP_CLIENT_SSL_MODE_NONE; client->proxy_conn = smtp_client_connection_create(smtp_client, SMTP_PROTOCOL_SMTP, set->submission_relay_host, set->submission_relay_port, ssl_mode, &smtp_set); smtp_client_connection_connect(client->proxy_conn, client_proxy_ready_cb, client); }
void FV3_(firwindow)::Kaiser(fv3_float_t w[], const long N, fv3_float_t beta) { long i; const fv3_float_t M = N-1; fv3_float_t inv_izbeta = 1.0 / i_zero(M_PI*beta); for(i = 0;i < N;i ++) { w[i] = i_zero(M_PI*beta*sqrt(1-pow(2*(fv3_float_t)i/M-1, 2))) * inv_izbeta; } }
static void sdbox_update_header(struct sdbox_mailbox *mbox, struct mail_index_transaction *trans, const struct mailbox_update *update) { struct sdbox_index_header hdr, new_hdr; bool need_resize; if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0) { i_zero(&hdr); need_resize = TRUE; } new_hdr = hdr; if (update != NULL && !guid_128_is_empty(update->mailbox_guid)) { memcpy(new_hdr.mailbox_guid, update->mailbox_guid, sizeof(new_hdr.mailbox_guid)); } else if (guid_128_is_empty(new_hdr.mailbox_guid)) { guid_128_generate(new_hdr.mailbox_guid); } if (need_resize) { mail_index_ext_resize_hdr(trans, mbox->hdr_ext_id, sizeof(new_hdr)); } if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) { mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0, &new_hdr, sizeof(new_hdr)); } memcpy(mbox->mailbox_guid, new_hdr.mailbox_guid, sizeof(mbox->mailbox_guid)); }
static void stats_metric_settings_to_query(const struct stats_metric_settings *set, struct event_filter_query *query_r) { i_zero(query_r); /* generate fields for event filter */ if (array_is_created(&set->filter)) { struct event_filter_field *filter_fields; const char *const *filters; unsigned int i, count; filters = array_get(&set->filter, &count); i_assert(count % 2 == 0); count /= 2; filter_fields = t_new(struct event_filter_field, count + 1); for (i = 0; i < count; i++) { filter_fields[i].key = filters[i*2]; filter_fields[i].value = filters[i*2+1]; } query_r->fields = filter_fields; } /* add query to the event filter */ query_r->categories = t_strsplit_spaces(set->categories, " "); query_r->name = set->event_name; query_r->source_filename = t_strcut(set->source_location, ':'); query_r->source_linenum = set->parsed_source_linenum; }
void http_parser_init(struct http_parser *parser, const unsigned char *data, size_t size) { i_zero(parser); parser->begin = data; parser->cur = data; parser->end = data + size; }
int imap_metadata_unset(struct imap_metadata_transaction *imtrans, const char *entry) { struct mail_attribute_value value; i_zero(&value); return imap_metadata_set(imtrans, entry, &value); }
static void doveadm_print_formatted_init(void) { i_zero(&ctx); ctx.pool = pool_alloconly_create("doveadm formatted print", 1024); ctx.buf = str_new(ctx.pool, 256); p_array_init(&ctx.headers, ctx.pool, 8); ctx.idx = 0; }
void index_sort_list_finish(struct mail_search_sort_program *program) { i_zero(&static_node_cmp_context); static_node_cmp_context.program = program; static_node_cmp_context.reverse = (program->sort_program[0] & MAIL_SORT_FLAG_REVERSE) != 0; program->sort_list_finish(program); }
static void doveadm_print_formatted_header(const struct doveadm_print_header *hdr) { struct var_expand_table entry; i_zero(&entry); entry.key = '\0'; entry.long_key = p_strdup(ctx.pool, hdr->key); entry.value = NULL; array_append(&ctx.headers, &entry, 1); }
int imap_metadata_get_stream(struct imap_metadata_transaction *imtrans, const char *entry, struct mail_attribute_value *value_r) { enum mail_attribute_type type; const char *key; i_zero(value_r); if (!imap_metadata_entry2key(imtrans, entry, &type, &key)) return 0; return mailbox_attribute_get_stream(imtrans->box, type, key, value_r); }
void smtp_server_command_register(struct smtp_server *server, const char *name, smtp_server_cmd_start_func_t *func, enum smtp_server_command_flags flags) { struct smtp_server_command_reg cmd; i_zero(&cmd); cmd.name = name; cmd.func = func; cmd.flags = flags; array_append(&server->commands_reg, &cmd, 1); server->commands_unsorted = TRUE; }
int imap_status_parse_items(struct client_command_context *cmd, const struct imap_arg *args, struct imap_status_items *items_r) { const char *item; enum mailbox_status_items status = 0; enum mailbox_metadata_items metadata = 0; if (IMAP_ARG_IS_EOL(args)) { client_send_command_error(cmd, "Empty status list."); return -1; } i_zero(items_r); for (; !IMAP_ARG_IS_EOL(args); args++) { if (!imap_arg_get_atom(args, &item)) { /* list may contain only atoms */ client_send_command_error(cmd, "Status list contains non-atoms."); return -1; } item = t_str_ucase(item); if (strcmp(item, "MESSAGES") == 0) status |= STATUS_MESSAGES; else if (strcmp(item, "RECENT") == 0) status |= STATUS_RECENT; else if (strcmp(item, "UIDNEXT") == 0) status |= STATUS_UIDNEXT; else if (strcmp(item, "UIDVALIDITY") == 0) status |= STATUS_UIDVALIDITY; else if (strcmp(item, "UNSEEN") == 0) status |= STATUS_UNSEEN; else if (strcmp(item, "HIGHESTMODSEQ") == 0) status |= STATUS_HIGHESTMODSEQ; else if (strcmp(item, "X-SIZE") == 0) metadata |= MAILBOX_METADATA_VIRTUAL_SIZE; else if (strcmp(item, "X-GUID") == 0) metadata |= MAILBOX_METADATA_GUID; else { client_send_command_error(cmd, t_strconcat( "Invalid status item ", item, NULL)); return -1; } } items_r->status = status; items_r->metadata = metadata; return 0; }
static void main_preinit(void) { struct module_dir_load_settings mod_set; i_zero(&mod_set); mod_set.abi_version = DOVECOT_ABI_VERSION; mod_set.require_init_funcs = TRUE; modules = module_dir_load(STATS_MODULE_DIR, NULL, &mod_set); module_dir_init(modules); restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); }
static int master_connection_input_line(struct master_connection *conn, const char *line) { const char *const *args = t_strsplit_tabescaped(line); struct mail_storage_service_input input; struct mail_storage_service_user *service_user; struct mail_user *user; const char *str, *error; unsigned int max_recent_msgs; int ret; /* <username> <mailbox> <session ID> <max_recent_msgs> [i][o] */ if (str_array_length(args) != 5 || str_to_uint(args[3], &max_recent_msgs) < 0 || args[4][0] == '\0') { i_error("Invalid input from master: %s", line); return -1; } i_zero(&input); input.module = "mail"; input.service = "indexer-worker"; input.username = args[0]; /* if session-id is given, use it as a prefix to a unique session ID. we can't use the session-id directly or stats process will complain about duplicates. (especially LMTP would use the same session-id for multiple users' indexing at the same time.) */ if (args[2][0] != '\0') input.session_id_prefix = args[2]; if (mail_storage_service_lookup_next(conn->storage_service, &input, &service_user, &user, &error) <= 0) { i_error("User %s lookup failed: %s", args[0], error); ret = -1; } else { indexer_worker_refresh_proctitle(user->username, args[1], 0, 0); ret = index_mailbox(conn, user, args[1], max_recent_msgs, args[4]); /* refresh proctitle before a potentially long-running user unref */ indexer_worker_refresh_proctitle(user->username, "(deinit)", 0, 0); mail_user_unref(&user); mail_storage_service_user_unref(&service_user); indexer_worker_refresh_proctitle(NULL, NULL, 0, 0); } str = ret < 0 ? "-1\n" : "100\n"; return write_full(conn->fd, str, strlen(str)); }
struct login_proxy_record * login_proxy_state_get(struct login_proxy_state *state, const struct ip_addr *ip, in_port_t port) { struct login_proxy_record *rec, key; i_zero(&key); key.ip = *ip; key.port = port; rec = hash_table_lookup(state->hash, &key); if (rec == NULL) { rec = p_new(state->pool, struct login_proxy_record, 1); rec->ip = *ip; rec->port = port; hash_table_insert(state->hash, rec, rec); }
static void client_init_urlauth(struct client *client) { static const char *access_apps[] = { "submit+", NULL }; struct imap_urlauth_config config; i_zero(&config); config.url_host = client->set->imap_urlauth_host; config.url_port = client->set->imap_urlauth_port; config.socket_path = t_strconcat(client->user->set->base_dir, "/"IMAP_URLAUTH_SOCKET_NAME, NULL); config.session_id = client->session_id; config.access_anonymous = client->user->anonymous; config.access_user = client->user->username; config.access_service = "submission"; config.access_applications = access_apps; client->urlauth_ctx = imap_urlauth_init(client->user, &config); }
static int dsync_mailbox_tree_fix_guid_duplicate(struct dsync_mailbox_tree *tree, struct dsync_mailbox_node *node1, struct dsync_mailbox_node *node2) { struct mailbox *box; struct mailbox_update update; struct dsync_mailbox_node *change_node; const char *change_vname; int ret = 0; i_zero(&update); guid_128_generate(update.mailbox_guid); /* just in case the duplication exists in both sides, make them choose the same node */ if (strcmp(dsync_mailbox_node_get_full_name(tree, node1), dsync_mailbox_node_get_full_name(tree, node2)) <= 0) change_node = node1; else change_node = node2; change_vname = dsync_mailbox_node_get_full_name(tree, change_node); i_error("Duplicate mailbox GUID %s for mailboxes %s and %s - " "giving a new GUID %s to %s", guid_128_to_string(node1->mailbox_guid), dsync_mailbox_node_get_full_name(tree, node1), dsync_mailbox_node_get_full_name(tree, node2), guid_128_to_string(update.mailbox_guid), change_vname); i_assert(node1->ns != NULL && node2->ns != NULL); box = mailbox_alloc(change_node->ns->list, change_vname, 0); if (mailbox_update(box, &update) < 0) { i_error("Couldn't update mailbox %s GUID: %s", change_vname, mailbox_get_last_internal_error(box, NULL)); ret = -1; } else { memcpy(change_node->mailbox_guid, update.mailbox_guid, sizeof(change_node->mailbox_guid)); } mailbox_free(&box); return ret; }
void test_fs_async(const char *test_name, enum fs_properties properties, const char *driver, const char *args) { struct fs_settings fs_set; struct fs *fs; struct test_fs *test_fs; const char *error; i_zero(&fs_set); if (fs_init(driver, args, &fs_set, &fs, &error) < 0) i_fatal("fs_init() failed: %s", error); test_fs = test_fs_get(fs); test_fs->properties = properties; test_fs_async_write(test_name, fs); test_fs_async_copy(test_name, fs); fs_deinit(&fs); }
static void drop_privileges(void) { struct restrict_access_settings set; const char *error; /* by default we don't drop any privileges, but keep running as root. */ restrict_access_get_env(&set); if (set.uid != 0) { /* open config connection before dropping privileges */ struct master_service_settings_input input; struct master_service_settings_output output; i_zero(&input); input.module = "mail"; input.service = "indexer-worker"; (void)master_service_settings_read(master_service, &input, &output, &error); } restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); }
static int auth_server_input_mech(struct auth_server_connection *conn, const char *const *args) { struct auth_mech_desc mech_desc; if (conn->handshake_received) { i_error("BUG: Authentication server already sent handshake"); return -1; } if (args[0] == NULL) { i_error("BUG: Authentication server sent broken MECH line"); return -1; } i_zero(&mech_desc); mech_desc.name = p_strdup(conn->pool, args[0]); if (strcmp(mech_desc.name, "PLAIN") == 0) conn->has_plain_mech = TRUE; for (args++; *args != NULL; args++) { if (strcmp(*args, "private") == 0) mech_desc.flags |= MECH_SEC_PRIVATE; else if (strcmp(*args, "anonymous") == 0) mech_desc.flags |= MECH_SEC_ANONYMOUS; else if (strcmp(*args, "plaintext") == 0) mech_desc.flags |= MECH_SEC_PLAINTEXT; else if (strcmp(*args, "dictionary") == 0) mech_desc.flags |= MECH_SEC_DICTIONARY; else if (strcmp(*args, "active") == 0) mech_desc.flags |= MECH_SEC_ACTIVE; else if (strcmp(*args, "forward-secrecy") == 0) mech_desc.flags |= MECH_SEC_FORWARD_SECRECY; else if (strcmp(*args, "mutual-auth") == 0) mech_desc.flags |= MECH_SEC_MUTUAL_AUTH; } array_append(&conn->available_auth_mechs, &mech_desc, 1); return 0; }
int sdbox_read_header(struct sdbox_mailbox *mbox, struct sdbox_index_header *hdr, bool log_error, bool *need_resize_r) { struct mail_index_view *view; const void *data; size_t data_size; int ret = 0; i_assert(mbox->box.opened); view = mail_index_view_open(mbox->box.index); mail_index_get_header_ext(view, mbox->hdr_ext_id, &data, &data_size); if (data_size < SDBOX_INDEX_HEADER_MIN_SIZE && (!mbox->box.creating || data_size != 0)) { if (log_error) { mailbox_set_critical(&mbox->box, "sdbox: Invalid dbox header size"); } ret = -1; } else { i_zero(hdr); memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr))); if (guid_128_is_empty(hdr->mailbox_guid)) ret = -1; else { /* data is valid. remember it in case mailbox is being reset */ mail_index_set_ext_init_data(mbox->box.index, mbox->hdr_ext_id, hdr, sizeof(*hdr)); } } mail_index_view_close(&view); *need_resize_r = data_size < sizeof(*hdr); return ret; }
static int dcrypt_gnutls_pbkdf2(const unsigned char *password, size_t password_len, const unsigned char *salt, size_t salt_len, const char *algorithm, unsigned int rounds, buffer_t *result, unsigned int result_len, const char **error_r) { unsigned char buf[result_len]; /* only sha1 or sha256 is supported */ if (strncasecmp(algorithm, "sha1", 4) == 0) { pbkdf2_hmac_sha1(password_len, password, rounds, salt_len, salt, result_len, buf); } else if (strncasecmp(algorithm, "sha256", 6) == 0) { pbkdf2_hmac_sha256(password_len, password, rounds, salt_len, salt, result_len, buf); } else if (strncasecmp(algorithm, "sha512", 6) == 0) { struct hmac_sha512_ctx ctx; hmac_sha512_set_key(&ctx, password_len, password); PBKDF2(&ctx, hmac_sha512_update, hmac_sha512_digest, 64, rounds, salt_len, salt, result_len, buf); i_zero(&ctx); } else { *error_r = "Unsupported algorithm"; return -1; } buffer_append(result, buf, result_len); memset(buf, 0, sizeof(buf)); return 0; }
struct message_part * message_part_deserialize(pool_t pool, const void *data, size_t size, const char **error_r) { struct deserialize_context ctx; struct message_part *part; i_zero(&ctx); ctx.pool = pool; ctx.data = data; ctx.end = ctx.data + size; if (!message_part_deserialize_part(&ctx, NULL, 1, &part)) { *error_r = ctx.error; return NULL; } if (ctx.data != ctx.end) { *error_r = "Too much data"; return NULL; } return part; }
static int imap_master_client_parse_input(const char *const *args, pool_t pool, struct mail_storage_service_input *input_r, struct imap_master_input *master_input_r, const char **error_r) { const char *key, *value; unsigned int peer_dev_major = 0, peer_dev_minor = 0; i_zero(input_r); i_zero(master_input_r); master_input_r->client_input = buffer_create_dynamic(pool, 64); master_input_r->client_output = buffer_create_dynamic(pool, 16); master_input_r->state = buffer_create_dynamic(pool, 512); input_r->module = input_r->service = "imap"; /* we never want to do userdb lookup again when restoring the client. we have the userdb_fields cached already. */ input_r->flags_override_remove = MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP; if (args[0] == NULL) { *error_r = "Missing username in input"; return -1; } input_r->username = args[0]; for (args++; *args != NULL; args++) { value = strchr(*args, '='); if (value != NULL) key = t_strdup_until(*args, value++); else { key = *args; value = ""; } if (strcmp(key, "lip") == 0) { if (net_addr2ip(value, &input_r->local_ip) < 0) { *error_r = t_strdup_printf( "Invalid lip value: %s", value); return -1; } } else if (strcmp(key, "rip") == 0) { if (net_addr2ip(value, &input_r->remote_ip) < 0) { *error_r = t_strdup_printf( "Invalid rip value: %s", value); return -1; } } else if (strcmp(key, "peer_dev_major") == 0) { if (str_to_uint(value, &peer_dev_major) < 0) { *error_r = t_strdup_printf( "Invalid peer_dev_major value: %s", value); return -1; } } else if (strcmp(key, "peer_dev_minor") == 0) { if (str_to_uint(value, &peer_dev_minor) < 0) { *error_r = t_strdup_printf( "Invalid peer_dev_minor value: %s", value); return -1; } } else if (strcmp(key, "peer_ino") == 0) { if (str_to_ino(value, &master_input_r->peer_ino) < 0) { *error_r = t_strdup_printf( "Invalid peer_ino value: %s", value); return -1; } } else if (strcmp(key, "session") == 0) { input_r->session_id = value; } else if (strcmp(key, "session_created") == 0) { if (str_to_time(value, &input_r->session_create_time) < 0) { *error_r = t_strdup_printf( "Invalid session_created value: %s", value); return -1; } } else if (strcmp(key, "userdb_fields") == 0) { input_r->userdb_fields = t_strsplit_tabescaped(value); } else if (strcmp(key, "client_input") == 0) { if (base64_decode(value, strlen(value), NULL, master_input_r->client_input) < 0) { *error_r = t_strdup_printf( "Invalid client_input base64 value: %s", value); return -1; } } else if (strcmp(key, "client_output") == 0) { if (base64_decode(value, strlen(value), NULL, master_input_r->client_output) < 0) { *error_r = t_strdup_printf( "Invalid client_output base64 value: %s", value); return -1; } } else if (strcmp(key, "state") == 0) { if (base64_decode(value, strlen(value), NULL, master_input_r->state) < 0) { *error_r = t_strdup_printf( "Invalid state base64 value: %s", value); return -1; } } else if (strcmp(key, "tag") == 0) { master_input_r->tag = t_strdup(value); } else if (strcmp(key, "bad-done") == 0) { master_input_r->state_import_bad_idle_done = TRUE; } else if (strcmp(key, "idle-continue") == 0) { master_input_r->state_import_idle_continue = TRUE; } } if (peer_dev_major != 0 || peer_dev_minor != 0) { master_input_r->peer_dev = makedev(peer_dev_major, peer_dev_minor); } return 0; }
static void client_state_reset(struct client *client) { i_stream_unref(&client->state.data_input); i_zero(&client->state); }
struct client *client_create(int fd_in, int fd_out, const char *session_id, struct mail_user *user, struct mail_storage_service_user *service_user, const struct submission_settings *set, const char *helo, const unsigned char *pdata, unsigned int pdata_len) { const struct mail_storage_settings *mail_set; struct smtp_server_settings smtp_set; const char *ident; struct client *client; /* always use nonblocking I/O */ net_set_nonblock(fd_in, TRUE); net_set_nonblock(fd_out, TRUE); client = i_new(struct client, 1); client->user = user; client->service_user = service_user; client->set = set; client->session_id = i_strdup(session_id); i_zero(&smtp_set); smtp_set.hostname = set->hostname; smtp_set.login_greeting = set->login_greeting; smtp_set.max_recipients = set->submission_max_recipients; smtp_set.max_client_idle_time_msecs = CLIENT_IDLE_TIMEOUT_MSECS; smtp_set.debug = user->mail_debug; client->conn = smtp_server_connection_create(smtp_server, fd_in, fd_out, user->conn.remote_ip, user->conn.remote_port, FALSE, &smtp_set, &smtp_callbacks, client); client_proxy_create(client, set); smtp_server_connection_login(client->conn, client->user->username, helo, pdata, pdata_len, user->conn.ssl_secured); smtp_server_connection_start_pending(client->conn); mail_set = mail_user_set_get_storage_set(user); if (*set->imap_urlauth_host != '\0' && *mail_set->mail_attribute_dict != '\0') { /* Enable BURL capability only when urlauth dict is configured correctly */ client_init_urlauth(client); } submission_client_count++; DLLIST_PREPEND(&submission_clients, client); ident = mail_user_get_anvil_userip_ident(client->user); if (ident != NULL) { master_service_anvil_send(master_service, t_strconcat( "CONNECT\t", my_pid, "\tsubmission/", ident, "\n", NULL)); client->anvil_sent = TRUE; } if (hook_client_created != NULL) hook_client_created(&client); submission_refresh_proctitle(); return client; }
static int master_service_haproxy_read(struct master_service_haproxy_conn *hpconn) { /* reasonable max size for haproxy data */ unsigned char rbuf[1500]; const char *error; static union { unsigned char v1_data[HAPROXY_V1_MAX_HEADER_SIZE]; struct { const struct haproxy_header_v2 hdr; const struct haproxy_data_v2 data; } v2; } buf; struct ip_addr *real_remote_ip = &hpconn->conn.remote_ip; int fd = hpconn->conn.fd; struct ip_addr local_ip, remote_ip; in_port_t local_port, remote_port; size_t size,i,want; ssize_t ret; enum haproxy_version_t version; /* the protocol specification explicitly states that the protocol header must be sent as one TCP frame, meaning that we will get it in full with the first recv() call. */ i_zero(&buf); i_zero(rbuf); /* see if there is a HAPROXY protocol command waiting */ if ((ret = master_service_haproxy_recv(fd, &buf, sizeof(buf), MSG_PEEK))<=0) { if (ret < 0) i_info("haproxy: Client disconnected (rip=%s): %m", net_ip2addr(real_remote_ip)); return ret; /* see if there is a haproxy command, 8 is used later on as well */ } else if (ret >= 8 && memcmp(buf.v1_data, "PROXY", 5) == 0) { /* fine */ version = HAPROXY_VERSION_1; } else if ((size_t)ret >= sizeof(buf.v2.hdr) && memcmp(buf.v2.hdr.sig, haproxy_v2sig, sizeof(haproxy_v2sig)) == 0) { want = ntohs(buf.v2.hdr.len) + sizeof(buf.v2.hdr); if (want > sizeof(rbuf)) { i_error("haproxy: Client disconnected: Too long header (rip=%s)", net_ip2addr(real_remote_ip)); return -1; } if ((ret = master_service_haproxy_recv(fd, rbuf, want, MSG_WAITALL))<=0) { if (ret < 0) i_info("haproxy: Client disconnected (rip=%s): %m", net_ip2addr(real_remote_ip)); return ret; } if (ret != (ssize_t)want) { i_info("haproxy: Client disconnected: Failed to read full header (rip=%s)", net_ip2addr(real_remote_ip)); return -1; } memcpy(&buf, rbuf, sizeof(buf)); version = HAPROXY_VERSION_2; } else { /* it wasn't haproxy data */ i_error("haproxy: Client disconnected: " "Failed to read valid HAproxy data (rip=%s)", net_ip2addr(real_remote_ip)); return -1; } /* don't update true connection data until we succeed */ local_ip = hpconn->conn.local_ip; remote_ip = hpconn->conn.remote_ip; local_port = hpconn->conn.local_port; remote_port = hpconn->conn.remote_port; /* protocol version 2 */ if (version == HAPROXY_VERSION_2) { const struct haproxy_header_v2 *hdr = &buf.v2.hdr; const struct haproxy_data_v2 *data = &buf.v2.data; size_t hdr_len; i_assert(ret >= (ssize_t)sizeof(buf.v2.hdr)); if ((hdr->ver_cmd & 0xf0) != 0x20) { i_error("haproxy: Client disconnected: " "Unsupported protocol version (version=%02x, rip=%s)", (hdr->ver_cmd & 0xf0) >> 4, net_ip2addr(real_remote_ip)); return -1; } hdr_len = ntohs(hdr->len); size = sizeof(*hdr) + hdr_len; /* keep tab of how much address data there really is because because TLVs begin after that. */ i = 0; if (ret < (ssize_t)size) { i_error("haproxy(v2): Client disconnected: " "Protocol payload length does not match header " "(got=%"PRIuSIZE_T", expect=%"PRIuSIZE_T", rip=%s)", (size_t)ret, size, net_ip2addr(real_remote_ip)); return -1; } i += sizeof(*hdr); switch (hdr->ver_cmd & 0x0f) { case HAPROXY_CMD_LOCAL: /* keep local connection address for LOCAL */ /*i_debug("haproxy(v2): Local connection (rip=%s)", net_ip2addr(real_remote_ip));*/ break; case HAPROXY_CMD_PROXY: if ((hdr->fam & 0x0f) != HAPROXY_SOCK_STREAM) { /* UDP makes no sense currently */ i_error("haproxy(v2): Client disconnected: " "Not using TCP (type=%02x, rip=%s)", (hdr->fam & 0x0f), net_ip2addr(real_remote_ip)); return -1; } switch ((hdr->fam & 0xf0) >> 4) { case HAPROXY_AF_INET: /* IPv4 */ if (hdr_len < sizeof(data->addr.ip4)) { i_error("haproxy(v2): Client disconnected: " "IPv4 data is incomplete (rip=%s)", net_ip2addr(real_remote_ip)); return -1; } local_ip.family = AF_INET; local_ip.u.ip4.s_addr = data->addr.ip4.dst_addr; local_port = ntohs(data->addr.ip4.dst_port); remote_ip.family = AF_INET; remote_ip.u.ip4.s_addr = data->addr.ip4.src_addr; remote_port = ntohs(data->addr.ip4.src_port); i += sizeof(data->addr.ip4); break; case HAPROXY_AF_INET6: /* IPv6 */ if (hdr_len < sizeof(data->addr.ip6)) { i_error("haproxy(v2): Client disconnected: " "IPv6 data is incomplete (rip=%s)", net_ip2addr(real_remote_ip)); return -1; } local_ip.family = AF_INET6; memcpy(&local_ip.u.ip6.s6_addr, data->addr.ip6.dst_addr, 16); local_port = ntohs(data->addr.ip6.dst_port); remote_ip.family = AF_INET6; memcpy(&remote_ip.u.ip6.s6_addr, data->addr.ip6.src_addr, 16); remote_port = ntohs(data->addr.ip6.src_port); i += sizeof(data->addr.ip6); break; case HAPROXY_AF_UNSPEC: case HAPROXY_AF_UNIX: /* unsupported; ignored */ i_error("haproxy(v2): Unsupported address family " "(family=%02x, rip=%s)", (hdr->fam & 0xf0) >> 4, net_ip2addr(real_remote_ip)); break; default: /* unsupported; error */ i_error("haproxy(v2): Client disconnected: " "Unknown address family " "(family=%02x, rip=%s)", (hdr->fam & 0xf0) >> 4, net_ip2addr(real_remote_ip)); return -1; } break; default: i_error("haproxy(v2): Client disconnected: " "Invalid command (cmd=%02x, rip=%s)", (hdr->ver_cmd & 0x0f), net_ip2addr(real_remote_ip)); return -1; /* not a supported command */ } if (master_service_haproxy_parse_tlv(hpconn, rbuf+i, size-i, &error) < 0) { i_error("haproxy(v2): Client disconnected: " "Invalid TLV: %s (cmd=%02x, rip=%s)", error, (hdr->ver_cmd & 0x0f), net_ip2addr(real_remote_ip)); return -1; } /* protocol version 1 (soon obsolete) */ } else if (version == HAPROXY_VERSION_1) {
static int proxy_send_login(struct pop3_client *client, struct ostream *output) { struct dsasl_client_settings sasl_set; const unsigned char *sasl_output; size_t len; const char *mech_name, *error; string_t *str = t_str_new(128); i_assert(client->common.proxy_ttl > 1); if (client->proxy_xclient && !client->common.proxy_not_trusted) { string_t *fwd = t_str_new(128); for(const char *const *ptr = client->common.auth_passdb_args;*ptr != NULL; ptr++) { if (strncasecmp(*ptr, "forward_", 8) == 0) { if (str_len(fwd) > 0) str_append_c(fwd, '\t'); str_append_tabescaped(fwd, (*ptr)+8); } } str_printfa(str, "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u", net_ip2addr(&client->common.ip), client->common.remote_port, client_get_session_id(&client->common), client->common.proxy_ttl - 1); if (str_len(fwd) > 0) { str_append(str, " FORWARD="); base64_encode(str_data(fwd), str_len(fwd), str); } str_append(str, "\r\n"); /* remote supports XCLIENT, send it */ o_stream_nsend(output, str_data(str), str_len(str)); client->proxy_state = POP3_PROXY_XCLIENT; } else { client->proxy_state = POP3_PROXY_LOGIN1; } str_truncate(str, 0); if (client->common.proxy_mech == NULL) { /* send USER command */ str_append(str, "USER "); str_append(str, client->common.proxy_user); str_append(str, "\r\n"); o_stream_nsend(output, str_data(str), str_len(str)); return 0; } i_assert(client->common.proxy_sasl_client == NULL); i_zero(&sasl_set); sasl_set.authid = client->common.proxy_master_user != NULL ? client->common.proxy_master_user : client->common.proxy_user; sasl_set.authzid = client->common.proxy_user; sasl_set.password = client->common.proxy_password; client->common.proxy_sasl_client = dsasl_client_new(client->common.proxy_mech, &sasl_set); mech_name = dsasl_client_mech_get_name(client->common.proxy_mech); str_printfa(str, "AUTH %s ", mech_name); if (dsasl_client_output(client->common.proxy_sasl_client, &sasl_output, &len, &error) < 0) { client_log_err(&client->common, t_strdup_printf( "proxy: SASL mechanism %s init failed: %s", mech_name, error)); return -1; } if (len == 0) str_append_c(str, '='); else base64_encode(sasl_output, len, str); str_append(str, "\r\n"); o_stream_nsend(output, str_data(str), str_len(str)); proxy_free_password(&client->common); if (client->proxy_state != POP3_PROXY_XCLIENT) client->proxy_state = POP3_PROXY_LOGIN2; return 0; }
void imap_client_auth_result(struct client *client, enum client_auth_result result, const struct client_auth_reply *reply, const char *text) { struct imap_url url; string_t *referral; switch (result) { case CLIENT_AUTH_RESULT_SUCCESS: /* nothing to be done for IMAP */ break; case CLIENT_AUTH_RESULT_REFERRAL_SUCCESS: case CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN: /* IMAP referral [nologin] referral host=.. [port=..] [destuser=..] [reason=..] NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login. OK [...] Logged in, but you should use this server instead. .. [REFERRAL ..] (Reason from auth server) */ referral = t_str_new(128); i_zero(&url); url.userid = reply->destuser; url.auth_type = client->auth_mech_name; url.host.name = reply->host; if (reply->port != 143) url.port = reply->port; str_append(referral, "REFERRAL "); str_append(referral, imap_url_create(&url)); if (result == CLIENT_AUTH_RESULT_REFERRAL_SUCCESS) { client_send_reply_code(client, IMAP_CMD_REPLY_OK, str_c(referral), text); } else { client_send_reply_code(client, IMAP_CMD_REPLY_NO, str_c(referral), text); } break; case CLIENT_AUTH_RESULT_INVALID_BASE64: case CLIENT_AUTH_RESULT_ABORTED: client_send_reply(client, IMAP_CMD_REPLY_BAD, text); break; case CLIENT_AUTH_RESULT_AUTHFAILED_REASON: case CLIENT_AUTH_RESULT_MECH_INVALID: if (text[0] == '[') client_send_reply(client, IMAP_CMD_REPLY_NO, text); else { client_send_reply_code(client, IMAP_CMD_REPLY_NO, "ALERT", text); } break; case CLIENT_AUTH_RESULT_AUTHZFAILED: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_AUTHZFAILED, text); break; case CLIENT_AUTH_RESULT_TEMPFAIL: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_UNAVAILABLE, text); break; case CLIENT_AUTH_RESULT_SSL_REQUIRED: case CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_PRIVACYREQUIRED, text); break; case CLIENT_AUTH_RESULT_PASS_EXPIRED: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_EXPIRED, text); break; case CLIENT_AUTH_RESULT_LOGIN_DISABLED: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_CONTACTADMIN, text); break; case CLIENT_AUTH_RESULT_AUTHFAILED: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_AUTHFAILED, text); break; } }
void stats_dist_reset(struct stats_dist *stats) { unsigned int sample_count = stats->sample_count; i_zero(stats); stats->sample_count = sample_count; }