static gboolean pop3_transfer_stack(ZTransfer2 *s, ZStackedProxy **stacked) { Pop3Proxy *owner = Z_CAST(s->owner, Pop3Proxy); return pop3_policy_stack_hash_do(owner, stacked); }
/** * @fn void z_delete(z_t zip) * @brief Delete the ZIP context. * @param zip The pointer to release. */ void z_delete(z_t zip) { struct z_s* z = Z_CAST(zip); if(!Z_VALID(z)) return; z_close(z); z->magic = 0; free(z); }
/** * z_transfer2_ps_iface_set_stacked_verdict: * @self: ZProxyStackIface instance * @verdict: verdict sent by the child proxy * @description: additional information about @decision * * This function is the virtual set_result method in the ZProxyStackIface * interface callable by child proxies. It simply stores the verdict sent * by the child proxy in self->stack_decision. * * NOTE: this function runs in the thread of the child proxy and there is no * synchronization between this and the main proxy thread except for the fact * that the child proxy should call this function before he sends anything * and HTTP will make use of this value when it first receives something, * thus there must be at least one context switch in between, and the HTTP * is possibly sleeping when this function is called. **/ static void z_transfer2_ps_iface_set_stacked_verdict(ZProxyStackIface *s, ZVerdict verdict, const gchar *description) { ZTransfer2PSIface *self = Z_CAST(s, ZTransfer2PSIface); g_string_assign(self->transfer->stack_info, description ? description : ""); self->transfer->stack_decision = verdict; }
/** * @fn void z_set_dir_delimiter(z_t zip, char delimiter) * @brief Change the directory delimiter. * @param zip ZIP context. * @param delimiter The new deimiter. */ void z_set_dir_delimiter(z_t zip, char delimiter) { struct z_s* z = Z_CAST(zip); if(!Z_VALID(z)) { logger(LOG_ERR, "Invalid zip pointer!\n"); return; } z->dir_delimiter = delimiter; }
void z_proxy_ssl_host_iface_free_method(ZObject *s) { ZProxySslHostIface *self = Z_CAST(s, ZProxySslHostIface); X509_free(self->server_cert); z_object_free_method(s); }
/** * finger_config: **/ static gboolean finger_config(ZProxy *s) { FingerProxy *self = Z_CAST(s, FingerProxy); finger_config_set_defaults(self); finger_register_vars(self); return Z_SUPER(s, ZProxy)->config(s); }
/** * @fn char z_get_dir_delimiter(z_t zip) * @brief Get the current directory delimiter. * @param zip ZIP context. * @return The deimiter. */ char z_get_dir_delimiter(z_t zip) { struct z_s* z = Z_CAST(zip); if(!Z_VALID(z)) { logger(LOG_ERR, "Invalid zip pointer!\n"); return 0; } return z->dir_delimiter; }
/** * http_set_content_length: * @self: ZProxyStackIface instance * @content_length: the length of the content to be transferred * * This function is the virtual set_content_length method in the * ZProxyStackIface interface callable by child proxies. It simply stores * the future size of the transferred data blob. This information will then * be used by the transfer code to decide whether to include a * content-length header. Calling this function is not mandatory by the * child proxy, if it is not called chunked mode transfer-encoding will be * used. */ static void z_transfer2_ps_iface_set_content_hint(ZProxyStackIface *s, gint64 content_length) { ZTransfer2PSIface *self = Z_CAST(s, ZTransfer2PSIface); self->transfer->child_content_length_hint = content_length; self->transfer->child_content_length_hint_set = TRUE; }
static ZProxyIface * z_transfer2_ps_iface_new(ZTransfer2 *transfer) { ZTransfer2PSIface *self; self = Z_CAST(z_proxy_stack_iface_new(Z_CLASS(ZTransfer2PSIface), transfer->owner), ZTransfer2PSIface); self->transfer = transfer; return &self->super; }
/** * finger_proxy_new: * @params: ZProxyParams structure * * Finger proxy constructor. Allocates and initializes a proxy instance, * starts proxy thread. **/ static ZProxy * finger_proxy_new(ZProxyParams *params) { FingerProxy *self; z_enter(); self = Z_CAST(z_proxy_new(Z_CLASS(FingerProxy), params), FingerProxy); z_return((ZProxy *) self); }
/** * @fn int z_get_global_zinfo(z_t zip, unz_global_info *ginfo) * @brief Get the global zip info (open must be all). * @param zip ZIP context. * @param ginfo The result infos. * @return -1 on error else 0. */ int z_get_global_zinfo(z_t zip, unz_global_info *ginfo) { struct z_s* z = Z_CAST(zip); if(!Z_VALID_OPEN(z)) { logger(LOG_ERR, "Invalid zip pointer!\n"); return -1; } memcpy(ginfo, &z->ginfo, sizeof(unz_global_info)); return 0; }
/** * anypy_proxy_new: * @params: parameters for the AnyPyProxy class constructor * * This function is called upon startup to create a new AnyPy proxy. **/ ZProxy * anypy_proxy_new(ZProxyParams *params) { AnyPyProxy *self; z_enter(); self = Z_CAST(z_proxy_new(Z_CLASS(AnyPyProxy), params), AnyPyProxy); z_return(&self->super); }
static void z_certificate_chain_free_method(ZObject *s) { ZCertificateChain *self = Z_CAST(s, ZCertificateChain); if (self->cert) X509_free(self->cert); sk_X509_pop_free(self->chain, X509_free); z_object_free_method(s); }
ZProxyIface * z_proxy_ssl_host_iface_new(ZProxy *owner) { ZProxySslHostIface *self; self = Z_CAST(z_proxy_iface_new(Z_CLASS(ZProxySslHostIface), owner), ZProxySslHostIface); self->server_cert = owner->ssl_opts.peer_cert[EP_SERVER]; CRYPTO_add(&self->server_cert->references, 1, CRYPTO_LOCK_X509); return &self->super; }
static gboolean telnet_client_read(ZStream *stream, GIOCondition cond G_GNUC_UNUSED, gpointer user_data) { TelnetProxy *self = Z_CAST(user_data, TelnetProxy); gboolean res; z_proxy_enter(self); res = telnet_read(self, stream, EP_CLIENT); z_proxy_return(self, res); }
/** * anypy_config: * @s: AnyPyProxy instance casted to ZProxy * * This function is called upon startup to configure the proxy. * This calls the the __pre_config__, config and __post_config__ events. **/ static gboolean anypy_config(ZProxy *s) { AnyPyProxy *self = Z_CAST(s, AnyPyProxy); anypy_config_set_defaults(self); anypy_register_vars(self); if (Z_SUPER(s, ZProxy)->config(s)) { return TRUE; } return FALSE; }
/** * z_transfer2_timeout: * @user_data: ZTransfer2 instance passed as a generic pointer * * This function is a timeout-callback registered to terminate the * transfer loop when a specified time elapses. **/ static gboolean z_transfer2_timeout(gpointer user_data) { ZTransfer2 *self = Z_CAST(user_data, ZTransfer2); z_proxy_enter(self->owner); /*LOG This message indicates the data transfer timed out. */ z_proxy_log(self->owner, CORE_ERROR, 3, "Data transfer timed out; timeout='%ld'", self->timeout); z_transfer2_update_status(self, ZT2S_TIMEDOUT+ZT2S_FAILED+ZT2S_FINISHED, TRUE); z_proxy_leave(self->owner); return FALSE; }
/** * http_get_content_hint: * @self: ZProxyStackIface instance * @content_length: the length of the content to be transferred * * This function is the virtual get_content_length method in the * ZProxyStackIface interface callable by child proxies. */ static gboolean z_transfer2_ps_iface_get_content_hint(ZProxyStackIface *s, gint64 *content_length, const gchar **content_format) { ZTransfer2PSIface *self = Z_CAST(s, ZTransfer2PSIface); /* Note: Save it with a mutex because it's only be set in z_transfer2_setup in * other thread than this called. */ g_mutex_lock(self->transfer->startup_lock); *content_format = self->transfer->content_format; if (self->transfer->our_content_length_hint_set) *content_length = self->transfer->our_content_length_hint; else *content_length = -1; g_mutex_unlock(self->transfer->startup_lock); return TRUE; }
/** * @fn int z_open(z_t zip, const z_file_t filename) * @brief Open a new ZIP file. * @param zip The ZIP context. * @param filename ZIP file name. * @return 0 on success else -1. */ int z_open(z_t zip, const z_file_t filename) { struct z_s* z = Z_CAST(zip); if(!Z_VALID(z)) return -1; strcpy(z->filename, filename); /* Open the zip file */ z->ctx = unzOpen64(z->filename); if(!z->ctx) { logger(LOG_ERR, "Unable to open the zip file '%s'\n", z->filename); z_close(z); return -1; } /* Get info about the zip file */ if(unzGetGlobalInfo64(z->ctx, &z->ginfo) != UNZ_OK) { logger(LOG_ERR, "Unable to read the global info related to the '%s' zip file\n", z->filename); z_close(z); return -1; } return 0; }
static void anypy_main(ZProxy * s) { AnyPyProxy *self = Z_CAST(s, AnyPyProxy); ZPolicyObj *res; gboolean called; z_proxy_enter(self); if (!z_proxy_connect_server(&self->super, NULL, 0) || !anypy_stream_init(self)) { z_proxy_leave(self); return; } z_policy_lock(self->super.thread); res = z_policy_call(self->super.handler, "proxyThread", NULL, &called, self->super.session_id); z_policy_var_unref(res); z_policy_unlock(self->super.thread); z_proxy_return(self); }
/** * z_transfer2_timed_progress: * @user_data: ZTransfer2 instance passed as a generic pointer * * This function is the timeout callback registered to be called when the * interval specified by the timeout_progress variable elapses. This is * used for example to generate NOOPs in SMTP while transfer is downloading * data to the virus checking proxy. **/ static gboolean z_transfer2_timed_progress(gpointer user_data) { ZTransfer2 *self = Z_CAST(user_data, ZTransfer2); z_proxy_enter(self->owner); if (!z_transfer2_progress(self)) { /*LOG This message indicates that the data-transfer is interrupted by a timed progress callback and Zorp is closing the date-transfer channels. */ z_proxy_log(self->owner, CORE_ERROR, 3, "Data transfer interrupted by progress;"); z_transfer2_update_status(self, ZT2S_FAILED+ZT2S_FINISHED, TRUE); } z_timeout_source_set_timeout(self->progress_source, self->progress_interval); z_proxy_leave(self->owner); return TRUE; }
gboolean pop3_data_transfer(Pop3Proxy *owner) { Pop3Transfer *t; GString *preamble; gboolean success; gchar buf[256]; z_proxy_enter(owner); preamble = g_string_new(owner->response->str); if (owner->response_param->len) { g_string_append_c(preamble, ' '); g_string_append(preamble, owner->response_param->str); } g_string_append(preamble, "\r\n"); t = Z_CAST(z_dot_transfer_new(Z_CLASS(Pop3Transfer), &owner->super, owner->poll, owner->super.endpoints[EP_SERVER], owner->super.endpoints[EP_CLIENT], owner->buffer_length, owner->timeout, ZT2F_COMPLETE_COPY | ZT2F_PROXY_STREAMS_POLLED, preamble), Pop3Transfer); z_transfer2_set_content_format(&t->super.super, "email"); z_stream_line_set_nul_nonfatal(owner->super.endpoints[EP_SERVER], TRUE); if (owner->policy_enable_longline) z_stream_line_set_split(owner->super.endpoints[EP_SERVER], TRUE); success = z_transfer2_simple_run(&t->super.super); z_stream_line_set_split(owner->super.endpoints[EP_SERVER], FALSE); z_stream_line_set_nul_nonfatal(owner->super.endpoints[EP_SERVER], FALSE); if (t->super.dst_write_state == DOT_DW_PREAMBLE) { /* nothing was written to destination */ switch (z_transfer2_get_stack_decision(&t->super.super)) { case ZV_REJECT: /*LOG This message indicates that the stacked proxy rejected the content and Zorp rejects the response. */ z_proxy_log(owner, POP3_ERROR, 2, "Stacked proxy rejected contents; info='%s'", z_transfer2_get_stack_info(&t->super.super)); g_snprintf(buf, sizeof(buf), "Content rejected (%s)", z_transfer2_get_stack_info(&t->super.super)); if (owner->reject_by_mail) pop3_error_msg(owner, buf); else pop3_response_reject(owner, buf); break; case ZV_ERROR: g_snprintf(buf, sizeof(buf), "Error occurred while transferring data (%s)", z_transfer2_get_stack_info(&t->super.super)); pop3_response_reject(owner, buf); owner->pop3_state = POP3_STATE_QUIT; break; default: pop3_response_write(owner); pop3_write_client(owner, ".\r\n"); break; } } else { pop3_write_client(owner, ".\r\n"); } if (owner->from) { g_string_free(owner->from, TRUE); owner->from = NULL; } if (owner->to) { g_string_free(owner->to, TRUE); owner->to = NULL; } if (owner->subject) { g_string_free(owner->subject, TRUE); owner->subject = NULL; } z_object_unref(&t->super.super.super); z_proxy_return(owner, success); }
/** * finger_main: * @s: FingerProxy instance * * main proxy routine. **/ static void finger_main(ZProxy *s) { FingerProxy *self = Z_CAST(s, FingerProxy); z_proxy_enter(self); if (!finger_init_client_stream(self)) z_proxy_return(self); /*LOG This debug message is about proxy state when start to fetching request */ z_proxy_log(self, FINGER_DEBUG, 6, "fetching request;"); if (!finger_fetch_request(self)) { char *errmsg = "Finger protocol or disallowed protocol element, request denied.\r\n"; gsize bytes_written; z_stream_write(self->super.endpoints[EP_CLIENT], errmsg, strlen(errmsg), &bytes_written, NULL); z_proxy_return(self); } /*LOG This debug message is about proxy state when finger fetched request and asking policy about it */ z_proxy_log(self, FINGER_DEBUG, 6, "asking policy;"); if (!finger_query_policy(self)) z_proxy_return(self); /*LOG This debug message is about proxy state when finger start connect to server. */ z_proxy_log(self, FINGER_DEBUG, 6, "connecting server;"); /* this sets the server side endpoint if successful */ if (!z_proxy_connect_server(&self->super, NULL, 0)) z_proxy_return(self); if (!finger_init_server_stream(self)) z_proxy_return(self); /*LOG This debug message is about proxy state when finger start send the request to server. */ z_proxy_log(self, FINGER_DEBUG, 6, "sending request;"); if (!finger_send_request(self)) z_proxy_return(self); /*LOG This debug message is about proxy state when finger start to copy server answer to client. */ z_proxy_log(self, FINGER_DEBUG, 6, "copying response;"); if (!finger_copy_response(self)) z_proxy_return(self); /*LOG This debug message is about proxy state when finger stop it's work. */ z_proxy_log(self, FINGER_DEBUG, 6, "everything is done;"); z_proxy_return(self); }
static GIOStatus http_transfer_src_read(ZTransfer2 *s, ZStream *stream, gchar *buf, gsize count, gsize *bytes_read, GError **err) { HttpTransfer *self = Z_CAST(s, HttpTransfer); HttpProxy *owner = Z_CAST(s->owner, HttpProxy); GError *local_error = NULL; gsize br; GIOStatus res = G_IO_STATUS_NORMAL; if (self->src_read_state == HTTP_SR_INITIAL) self->src_read_state = HTTP_SR_PUSH_HEADERS; if (self->src_read_state >= HTTP_SR_PUSH_HEADERS && self->src_read_state <= HTTP_SR_PUSH_HEADERS_MAX) { if (self->push_mime_headers && self->stacked_preamble->len > 0) { gint move; *bytes_read = 0; move = MIN(count, self->stacked_preamble->len - self->stacked_preamble_ofs); memmove(buf, self->stacked_preamble->str + self->stacked_preamble_ofs, move); self->stacked_preamble_ofs += move; *bytes_read = move; if (self->stacked_preamble_ofs == self->stacked_preamble->len) { z_transfer2_set_proxy_out(s, FALSE); self->src_read_state = HTTP_SR_READ_INITIAL; } return G_IO_STATUS_NORMAL; } else { self->src_read_state = HTTP_SR_READ_INITIAL; } } *bytes_read = 0; if (self->src_chunked) { /* read as a chunked stream */ switch (self->src_read_state) { case HTTP_SR_READ_INITIAL: self->src_whole_length = 0; self->src_read_state = HTTP_SR_READ_CHUNK_LENGTH; z_stream_line_set_poll_partial(stream, FALSE); /* fallthrough */ case HTTP_SR_READ_CHUNK_LENGTH: { gchar line_buf[32], *line; gsize line_length; guint32 chunk_length; gchar *end; res = z_stream_line_get(stream, &line, &line_length, NULL); if (res == G_IO_STATUS_NORMAL) { /* a complete line was read, check if it is a valid chunk length */ if (line_length >= sizeof(line_buf) - 1) { /*LOG This message indicates that the chunk length line is too long. It is likely caused by a buggy client or server. */ z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Chunk length line too long; line='%.*s'", (gint) line_length, line); res = G_IO_STATUS_ERROR; break; } /* we already checked that line_buf is large enough */ memcpy(line_buf, line, line_length); line_buf[line_length] = 0; chunk_length = strtoul(line_buf, &end, 16); if (end == line_buf) { /* hmm... invalid chunk length */ /*LOG This message indicates that the chunk length is invalid. It is likely caused by a buggy client or server. */ z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Invalid chunk length; line='%s'", line_buf); res = G_IO_STATUS_ERROR; break; } /* * NOTE: the string pointed by end is NUL terminated, thus * we will not overflow our buffer */ while (*end == ' ') end++; if (*end == ';') { /* ignore and strip chunk extensions */ *end = 0; } if (*end) { /* hmm... invalid chunk length */ /*LOG This message indicates that the chunk length is invalid. It is likely caused by a buggy client or server. */ z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Invalid chunk length; line='%s'", line_buf); res = G_IO_STATUS_ERROR; break; } if ((owner->max_chunk_length && chunk_length > owner->max_chunk_length) || (chunk_length & 0x80000000)) { /*LOG This message indicates that the length of the chunk is larger than allowed or is a negative number. Check the 'max_chunk_length' attribute. */ z_proxy_log(self->super.owner, HTTP_POLICY, 2, "Chunk too large; length='%d', max_chunk_length='%d'", chunk_length, owner->max_chunk_length); res = G_IO_STATUS_ERROR; break; } if (owner->max_body_length && (guint) self->src_whole_length + chunk_length > owner->max_body_length) { /* this chunk would be over body_length limit */ chunk_length = owner->max_body_length - self->src_whole_length; self->src_chunk_left = chunk_length; self->force_nonpersistent_mode = TRUE; self->src_chunk_truncated = TRUE; } self->src_chunk_left = chunk_length; self->src_last_chunk = chunk_length == 0; self->src_read_state = HTTP_SR_READ_CHUNK; z_stream_line_set_poll_partial(stream, TRUE); /* fall through */ } else break; } case HTTP_SR_READ_CHUNK: if (!self->src_last_chunk) { res = z_stream_read(stream, buf, MIN(self->src_chunk_left, count), &br, &local_error); if (res == G_IO_STATUS_NORMAL) { self->src_whole_length += br; self->src_chunk_left -= br; *bytes_read = br; } else if (res == G_IO_STATUS_EOF) { /* unexpected eof */ /*LOG This message indicates that Zorp unexpectedly got EOF during chunk encoded data transfer. It is likely a caused by a buggy client or server. */ z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Unexpected EOF while dechunking stream;"); res = G_IO_STATUS_ERROR; break; } if (self->src_chunk_left == 0) { self->src_read_state = HTTP_SR_READ_FOOTER; z_stream_line_set_poll_partial(stream, FALSE); } break; } else { self->src_read_state = HTTP_SR_READ_FOOTER; z_stream_line_set_poll_partial(stream, FALSE); /* fallthrough */ } case HTTP_SR_READ_FOOTER: { gchar *line; gsize line_length; if (!self->src_chunk_truncated) { res = z_stream_line_get(stream, &line, &line_length, NULL); } else { res = G_IO_STATUS_EOF; } if (res == G_IO_STATUS_NORMAL) { if (line_length != 0) { /*LOG This message indicates that the chunk footer contains data. It is likely caused by a buggy client or server. */ z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Chunk footer is not an empty line;"); res = G_IO_STATUS_ERROR; break; } if (self->src_last_chunk) { res = G_IO_STATUS_EOF; } else { self->src_read_state = HTTP_SR_READ_CHUNK_LENGTH; z_stream_line_set_poll_partial(stream, TRUE); /* come back later */ res = G_IO_STATUS_AGAIN; } break; } break; } } } else { /* copy until EOF or self->content_length bytes */ if (self->content_length == HTTP_LENGTH_NONE) { res = G_IO_STATUS_EOF; } else { if (self->src_read_state == HTTP_SR_INITIAL) { self->src_whole_length = 0; self->src_read_state = HTTP_SR_READ_ENTITY; } if (self->content_length == HTTP_LENGTH_UNKNOWN) { if (owner->max_body_length && self->src_whole_length + count >= owner->max_body_length) { count = owner->max_body_length - self->src_whole_length; } if (count == 0) { self->force_nonpersistent_mode = TRUE; res = G_IO_STATUS_EOF; } else res = z_stream_read(stream, buf, count, &br, &local_error); } else { /* for specified content-length, max_body_length has already been processed, and content_length contains the number of bytes to be transferred, but maximum max_body_length */ if (self->content_length >= 0 && (guint64) self->content_length == self->src_whole_length) res = G_IO_STATUS_EOF; else res = z_stream_read(stream, buf, MIN(count, self->content_length - self->src_whole_length), &br, &local_error); } if (res == G_IO_STATUS_NORMAL) { self->src_whole_length += br; *bytes_read = br; } } } if (local_error) g_propagate_error(err, local_error); return res; }
telnet_client_read(ZStream *stream, GIOCondition cond G_GNUC_UNUSED, gpointer user_data) { TelnetProxy *self = Z_CAST(user_data, TelnetProxy); gboolean res; z_proxy_enter(self); res = telnet_read(self, stream, EP_CLIENT); z_proxy_return(self, res); } static gboolean telnet_server_read(ZStream *stream G_GNUC_UNUSED, GIOCondition cond G_GNUC_UNUSED, gpointer user_data) { TelnetProxy *self = Z_CAST(user_data, TelnetProxy); gboolean res; z_proxy_enter(self); res = telnet_read(self, stream, EP_SERVER); z_proxy_return(self, res); } static void telnet_init_stream(TelnetProxy *self, ZEndpoint ep, ZStreamCallback cb, gpointer user_data, GDestroyNotify data_notify) { ZStream *stream = self->super.endpoints[ep] = z_stream_push(self->super.endpoints[ep], z_stream_buf_new(NULL, 256 * 1024, Z_SBF_IMMED_FLUSH));
static GIOStatus pop3_transfer_src_read(ZTransfer2 *s, ZStream *stream, gchar *buf, gsize count, gsize *bytes_read, GError **err) { GIOStatus ret; Pop3Transfer *self = Z_CAST(s, Pop3Transfer); Pop3Proxy *owner = Z_CAST(s->owner, Pop3Proxy); ret = Z_SUPER(s, ZTransfer2)->src_read(s, stream, buf, count, bytes_read, err); if (self->header_state < POP3_HEADER_END && (ret == G_IO_STATUS_NORMAL || (ret == G_IO_STATUS_AGAIN && *bytes_read > 0))) { if (*bytes_read == 0) { self->header_state = POP3_HEADER_END; } else { gsize bytes_need = *bytes_read; if (buf[0] != ' ' && buf[0] != '\t') { self->header_state = POP3_HEADER_NONE; self->actual_header = NULL; } while (buf[bytes_need - 1] == '\n' || buf[bytes_need - 1] == '\r' || buf[bytes_need - 1] == ' ') bytes_need--; z_trace(NULL, "Read header line; line='%.*s'", (gint) bytes_need, buf); if (self->header_state == POP3_HEADER_NONE) { if (g_ascii_strncasecmp(buf, FROM, MIN(__builtin_strlen(FROM), bytes_need)) == 0) { if (owner->from == NULL) { self->header_state = POP3_HEADER_INSIDE; owner->from = g_string_new_len(buf + __builtin_strlen(FROM), bytes_need - __builtin_strlen(FROM)); self->actual_header = owner->from; } else { /* FIXME: Log */ } } else if (g_ascii_strncasecmp(buf, TO, MIN(__builtin_strlen(TO), bytes_need)) == 0) { if (owner->to == NULL) { self->header_state = POP3_HEADER_INSIDE; owner->to = g_string_new_len(buf + __builtin_strlen(TO), bytes_need - __builtin_strlen(TO)); self->actual_header = owner->to; } else { /* FIXME: Log */ } } else if (g_ascii_strncasecmp(buf, SUBJECT, MIN(__builtin_strlen(SUBJECT), bytes_need)) == 0) { if (owner->subject == NULL) { self->header_state = POP3_HEADER_INSIDE; owner->subject = g_string_new_len(buf + __builtin_strlen(SUBJECT), bytes_need - __builtin_strlen(SUBJECT)); self->actual_header = owner->subject; } else { /* FIXME: Log */ } } } else { g_string_append(self->actual_header, "\r\n"); g_string_append_len(self->actual_header, buf, bytes_need); } } } return ret; }
} /** * z_transfer2_copy_src_to_dst: * @s: ZStream instance * @cond: condition which triggered this callback * @user_data: ZTransfer2 instance passed as a generic pointer * * This function is registered as the "readable" callback of the client-side * stream when no stacking is used, thus data is directly copied to the * server-side. **/ static gboolean z_transfer2_copy_src_to_dst(ZStream *s G_GNUC_UNUSED, GIOCondition cond G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) { ZTransfer2 *self = Z_CAST(user_data, ZTransfer2); z_proxy_enter(self->owner); z_transfer2_copy_data(self, ZT2E_SOURCE, ZT2E_DEST, NULL); z_proxy_leave(self->owner); return TRUE; } /** * z_transfer2_copy_src_to_down: * @s: ZStream instance * @cond: condition which triggered this callback * @user_data: ZTransfer2 instance passed as a generic pointer * * This function is registered as the "readable" callback of the client-side * stream when stacking is used, thus data must be copied to the stacked
gboolean z_proxy_ssl_host_iface_check_name_method(ZProxyHostIface *s, const gchar *host_name, gchar *reason_buf, gsize reason_len) { ZProxySslHostIface *self = Z_CAST(s, ZProxySslHostIface); gint ext_ndx; gboolean found = FALSE, result = FALSE; gchar pattern_buf[256]; if (self->hostname_checked) return self->hostname_check_result; pattern_buf[0] = 0; ext_ndx = X509_get_ext_by_NID(self->server_cert, NID_subject_alt_name, -1); if (ext_ndx >= 0) { /* ok, there's a subjectAltName extension, check that */ X509_EXTENSION *ext; STACK_OF(GENERAL_NAME) *alt_names; GENERAL_NAME *gen_name; ext = X509_get_ext(self->server_cert, ext_ndx); alt_names = X509V3_EXT_d2i(ext); if (alt_names) { gint num, i; num = sk_GENERAL_NAME_num(alt_names); for (i = 0; i < num; i++) { gen_name = sk_GENERAL_NAME_value(alt_names, i); if (gen_name->type == GEN_DNS) { guchar *dnsname = ASN1_STRING_data(gen_name->d.dNSName); guint dnsname_len = ASN1_STRING_length(gen_name->d.dNSName); if (dnsname_len > sizeof(pattern_buf) - 1) { found = TRUE; result = FALSE; break; } memcpy(pattern_buf, dnsname, dnsname_len); pattern_buf[dnsname_len] = 0; /* we have found a DNS name as alternative subject name */ found = TRUE; result = z_proxy_ssl_host_iface_check_wildcard(s->owner, host_name, pattern_buf); break; } else if (gen_name->type == GEN_IPADD) { z_inet_ntoa(pattern_buf, sizeof(pattern_buf), *(struct in_addr *) gen_name->d.iPAddress->data); found = TRUE; result = strcmp(host_name, pattern_buf) == 0; break; } } sk_GENERAL_NAME_free(alt_names); } } if (!found) { /* hmm. there was no subjectAltName (this is deprecated, but still * widely used), look up the Subject, most specific CN */ X509_NAME *name; name = X509_get_subject_name(self->server_cert); if (X509_NAME_get_text_by_NID(name, NID_commonName, pattern_buf, sizeof(pattern_buf)) != -1) { result = z_proxy_ssl_host_iface_check_wildcard(s->owner, host_name, pattern_buf); } } if (!result && reason_buf) { g_snprintf(reason_buf, reason_len, "Certificate does not belong to target host (certificate: %s, host %s)", pattern_buf, host_name); } self->hostname_checked = TRUE; self->hostname_check_result = result; return result; }
* smtp_transfer_src_read: * @s: ZTransfer instance * @stream: stream to read from * @buf: buffer to read into * @buf_len: size of the buffer * @bytes_read: the number of read bytes is returned here * @err: GLib error code * * Reads the incoming data stream, checks for EOF (a single '.' on its own), * removes '.' escaping and handles lines longer than the buffer size of ZStreamLine. * **/ static GIOStatus smtp_transfer_src_read(ZTransfer2 *s G_GNUC_UNUSED, ZStream *stream, gchar *buf, gsize buf_len, gsize *bytes_read, GError **err) { SmtpTransfer *self = Z_CAST(s, SmtpTransfer); SmtpProxy *owner = Z_CAST(self->super.owner, SmtpProxy); GIOStatus res; gsize line_len = buf_len - 2; /* to make space to closing CR LF */ if (G_UNLIKELY(self->src_read_state == SMTP_SR_INITIAL)) { if (owner->add_received_header) { if (self->received_line == NULL) { if (!smtp_generate_received(owner, &self->received_line)) self->src_read_state = SMTP_SR_DATA; } if (self->received_line)
**/ typedef struct _ZStreamBlob { ZStream super; gint64 pos; ZBlob *blob; GIOCondition poll_cond; } ZStreamBlob; extern ZClass ZStreamBlob__class; static gboolean z_stream_blob_watch_prepare(ZStream *s, GSource *src G_GNUC_UNUSED, gint *timeout) { ZStreamBlob *self = Z_CAST(s, ZStreamBlob); gboolean res; z_enter(); if (timeout) *timeout = -1; res = FALSE; self->poll_cond = 0; if (self->super.want_read) { self->poll_cond |= G_IO_IN; res = TRUE; } if (self->super.want_write) { self->poll_cond |= G_IO_OUT;