/* Converts a string from ISO-8859-1 encoding to UTF-8 encoding. */ static char * conv_from_iso_8859_1 (char *string) { if (is_ascii_string (string)) return string; else { size_t length = strlen (string); /* Each ISO-8859-1 character needs 2 bytes at worst. */ unsigned char *utf8_string = (unsigned char *) xmalloc (2 * length + 1); unsigned char *q = utf8_string; const char *str = string; const char *str_limit = str + length; while (str < str_limit) { unsigned int uc = (unsigned char) *str++; int n = u8_uctomb (q, uc, 6); assert (n > 0); q += n; } *q = '\0'; assert (q - utf8_string <= 2 * length); return (char *) utf8_string; } }
const char * auto_recode(const char *utf_str) { char *res; static char result_buf[MAX_BUFSIZE]; if (is_ascii_string (utf_str)) { res = (char*)utf_str; } else if (utf8_validate (utf_str)) { /* UTF-8 string */ /* Replace em dash with "#$%" sequence */ const char *utf_src = utf_str; char iso_8859_1[MAX_BUFSIZE]; if (simple_recode (utf_str, "UTF-8", "ISO8859-1", iso_8859_1) && utf8_validate(iso_8859_1)) utf_src = iso_8859_1; /* Now find out, how is UTF-8 string constructed */ if (is_cp1251 (utf_src)) { /* May be ISO8859-1 or CP1251 */ char tmp[MAX_BUFSIZE]; res = simple_recode (utf_src, "UTF-8", "ISO8859-1", tmp); if (res) res = simple_recode (res, "CP1251", "UTF-8", result_buf); if (!res) res = (char*)utf_src; } else { res = strncpy(result_buf, utf_src, MAX_BUFSIZE); } } else { res = simple_recode (utf_str, "CP1251", "UTF-8", result_buf); if (!res) res = (char*)utf_str; } return res; }
int decode_smb(u_char *buf, int len, u_char *obuf, int olen) { struct smbhdr *smb; int i, j, k; u_char *p, *q, *end; char *user, *pass; obuf[0] = '\0'; /* Skip NetBIOS session request. */ if (len < 4 || buf[0] != 0x81) return (0); buf += 2; GETSHORT(i, buf); len -= 4; if (len < i) return (0); buf += i; len -= i; end = buf + len; /* Parse SMBs. */ for (p = buf; p < end; p += i) { GETLONG(i, p); if (i > end - p || i < sizeof(*smb) + 32) continue; smb = (struct smbhdr *)p; if (memcmp(smb->proto, "\xffSMB", 4) != 0 || smb->cmd != 0x73) continue; user = pass = NULL; q = (u_char *)(smb + 1); if (*q == 10) { /* Pre NT LM 0.12 */ q += 15; j = pletohs(q); q += 2; if (j > i - (sizeof(*smb) + 15 + 6)) continue; pass = q + 6; user = pass + j; } else if (*q == 13) { /* NT LM 0.12 */ q += 15; j = pletohs(q); q += 2; k = pletohs(q); if (j > i - ((q - p) + 12) || k > i - ((q - p) + 11)) continue; pass = q + 12; user = pass + j + k; } else continue; /* XXX - skip null IPC sessions, etc. */ if (user && pass && strlen(user) && is_ascii_string(pass, j - 1)) { strlcat(obuf, user, olen); strlcat(obuf, " ", olen); strlcat(obuf, pass, olen); strlcat(obuf, "\n", olen); } } return (strlen(obuf)); }
bool is_ascii_string_list (string_list_ty *slp) { size_t i; if (slp != NULL) for (i = 0; i < slp->nitems; i++) if (!is_ascii_string (slp->item[i])) return false; return true; }
bool is_ascii_message (message_ty *mp) { const char *p = mp->msgstr; const char *p_end = p + mp->msgstr_len; for (; p < p_end; p++) if (!c_isascii ((unsigned char) *p)) return false; if (!is_ascii_string_list (mp->comment)) return false; if (!is_ascii_string_list (mp->comment_dot)) return false; /* msgid and msgid_plural are normally ASCII, so why checking? Because in complete UTF-8 environments they can be UTF-8, not ASCII. */ if (!is_ascii_string (mp->msgid)) return false; if (mp->msgid_plural != NULL && !is_ascii_string (mp->msgid_plural)) return false; return true; }
int decode_telnet(u_char *buf, int len, u_char *obuf, int olen) { if ((len = strip_telopts(buf, len)) == 0) return (0); if (!is_ascii_string(buf, len)) return (0); if (strip_lines(buf, Opt_lines) < 2) return (0); strlcpy(obuf, buf, olen); return (strlen(obuf)); }
static char *smtp_prepare_payload(const char *from_display_name, const char *from_angle_addr, const char *to_display_name, const char *to_angle_addr, const char *mailsubject, const char *mailbody) { char *tmp = NULL, *base64 = NULL, *base64_lf; char *localsubject = NULL, *localbody = NULL; char str_time[MAX_STRING_LEN]; struct tm *local_time; time_t email_time; /* prepare subject */ tmp = string_replace(mailsubject, "\r\n", " "); localsubject = string_replace(tmp, "\n", " "); zbx_free(tmp); if (FAIL == is_ascii_string(localsubject)) { /* split subject into multiple RFC 2047 "encoded-words" */ str_base64_encode_rfc2047(localsubject, &base64); zbx_free(localsubject); localsubject = base64; base64 = NULL; } /* prepare body */ tmp = string_replace(mailbody, "\r\n", "\n"); localbody = string_replace(tmp, "\n", "\r\n"); zbx_free(tmp); str_base64_encode_dyn(localbody, &base64, strlen(localbody)); /* wrap base64 encoded data with linefeeds */ base64_lf = str_linefeed(base64, ZBX_EMAIL_B64_MAXLINE, "\r\n"); zbx_free(base64); base64 = base64_lf; zbx_free(localbody); localbody = base64; base64 = NULL; /* prepare date */ time(&email_time); local_time = localtime(&email_time); strftime(str_time, MAX_STRING_LEN, "%a, %d %b %Y %H:%M:%S %z", local_time); /* e-mails are sent in 'SMTP/MIME e-mail' format because UTF-8 is used both in mailsubject and mailbody */ /* =?charset?encoding?encoded text?= format must be used for subject field */ tmp = zbx_dsprintf(tmp, "From: %s%s\r\n" "To: %s%s\r\n" "Date: %s\r\n" "Subject: %s\r\n" "MIME-Version: 1.0\r\n" "Content-Type: text/plain; charset=\"UTF-8\"\r\n" "Content-Transfer-Encoding: base64\r\n" "\r\n" "%s", NULL != from_display_name ? from_display_name : "", from_angle_addr, NULL != to_display_name ? to_display_name: "", to_angle_addr, str_time, localsubject, localbody); zbx_free(localsubject); zbx_free(localbody); return tmp; }
/** * Handle reception of a /Q2 */ static void g2_node_handle_q2(gnutella_node_t *n, const g2_tree_t *t) { const guid_t *muid; size_t paylen; const g2_tree_t *c; char *dn = NULL; char *md = NULL; uint32 iflags = 0; search_request_info_t sri; bool has_interest = FALSE; node_inc_rx_query(n); /* * As a G2 leaf, we cannot handle queries coming from UDP because we * are not supposed to get any! */ if (NODE_IS_UDP(n)) { g2_node_drop(G_STRFUNC, n, t, "coming from UDP"); return; } /* * The MUID of the query is the payload of the root node. */ muid = g2_tree_node_payload(t, &paylen); if (paylen != GUID_RAW_SIZE) { g2_node_drop(G_STRFUNC, n, t, "missing MUID"); return; } /* * Make sure we have never seen this query already. * * To be able to leverage on Gnutella's routing table to detect duplicates * over a certain lifespan, we are going to fake a minimal Gnutella header * with a message type of GTA_MSG_G2_SEARCH, which is never actually used * on the network. * * The TTL and hops are set to 1 and 0 initially, so that the message seems * to come from a neighbouring host and cannot be forwarded. * * When that is done, we will be able to call route_message() and have * all the necessary bookkeeping done for us. */ { struct route_dest dest; gnutella_header_set_muid(&n->header, muid); gnutella_header_set_function(&n->header, GTA_MSG_G2_SEARCH); gnutella_header_set_ttl(&n->header, 1); gnutella_header_set_hops(&n->header, 0); if (!route_message(&n, &dest)) return; /* Already accounted as duplicated, and logged */ } /* * Setup request information so that we can call search_request() * to process our G2 query. */ ZERO(&sri); sri.magic = SEARCH_REQUEST_INFO_MAGIC; /* * Handle the children of /Q2. */ G2_TREE_CHILD_FOREACH(t, c) { enum g2_q2_child ct = TOKENIZE(g2_tree_name(c), g2_q2_children); const char *payload; switch (ct) { case G2_Q2_DN: payload = g2_tree_node_payload(c, &paylen); if (payload != NULL && NULL == dn) { uint off = 0; /* Not NUL-terminated, need to h_strndup() it */ dn = h_strndup(payload, paylen); if (!query_utf8_decode(dn, &off)) { gnet_stats_count_dropped(n, MSG_DROP_MALFORMED_UTF_8); goto done; /* Drop the query */ } sri.extended_query = dn + off; sri.search_len = paylen - off; /* In bytes */ } break; case G2_Q2_I: if (!has_interest) iflags = g2_node_extract_interest(c); has_interest = TRUE; break; case G2_Q2_MD: payload = g2_tree_node_payload(c, &paylen); if (payload != NULL && NULL == md) { /* Not NUL-terminated, need to h_strndup() it */ md = h_strndup(payload, paylen); } break; case G2_Q2_NAT: sri.flags |= QUERY_F_FIREWALLED; break; case G2_Q2_SZR: /* Size limits */ if (g2_node_extract_size_request(c, &sri.minsize, &sri.maxsize)) sri.size_restrictions = TRUE; break; case G2_Q2_UDP: if (!sri.oob) g2_node_extract_udp(c, &sri, n); break; case G2_Q2_URN: g2_node_extract_urn(c, &sri); break; } } /* * When there is no /Q2/I, return a default set of information. */ if (!has_interest) iflags = G2_Q2_F_DFLT; /* * If there are meta-data, try to intuit which media types there are * looking for. * * The payload is XML looking like "<audio/>" or "<video/>" but there * can be attributes and we don't want to do a full XML parsing there. * Hence we'll base our analysis on simple lexical parsing, which is * why we call a routine to "intuit", not to "extract". * * Also, this is poorer than Gnutella's GGEP "M" because apparently there * can be only one single type, since the XML payload must obey some * kind of schema and there is an audio schema, a video schema, etc... * XML was just a wrong design choice there. */ if (md != NULL) sri.media_types = g2_node_intuit_media_type(md); /* * Validate the return address if OOB hit delivery is configured. */ if (sri.oob && !search_oob_is_allowed(n, &sri)) goto done; /* * Update statistics, as done in search_request_preprocess() for Gnutella. */ if (sri.exv_sha1cnt) { gnet_stats_inc_general(GNR_QUERY_G2_SHA1); if (NULL == dn) { int i; for (i = 0; i < sri.exv_sha1cnt; i++) { search_request_listener_emit(QUERY_SHA1, sha1_base32(&sri.exv_sha1[i].sha1), n->addr, n->port); } } } if (dn != NULL && !is_ascii_string(dn)) gnet_stats_inc_general(GNR_QUERY_G2_UTF8); if (dn != NULL) search_request_listener_emit(QUERY_STRING, dn, n->addr, n->port); if (!search_is_valid(n, 0, &sri)) goto done; /* * Perform the query. */ sri.g2_query = TRUE; sri.partials = booleanize(iflags & G2_Q2_F_PFS); sri.g2_wants_url = booleanize(iflags & G2_Q2_F_URL); sri.g2_wants_alt = booleanize(iflags & G2_Q2_F_A); sri.g2_wants_dn = booleanize(iflags & G2_Q2_F_DN); search_request(n, &sri, NULL); done: HFREE_NULL(dn); HFREE_NULL(md); }
void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) { GPtrArray *objects = NULL; GHashTable *ref_table = NULL; struct serialize_s ser_s; uint8_t offset_size = 0; uint8_t dict_param_size = 0; uint64_t num_objects = 0; uint64_t root_object = 0; uint64_t offset_table_index = 0; GByteArray *bplist_buff = NULL; uint64_t i = 0; uint8_t *buff = NULL; uint64_t *offsets = NULL; uint8_t pad[6] = { 0, 0, 0, 0, 0, 0 }; uint8_t trailer[BPLIST_TRL_SIZE]; //for string glong len = 0; int type = 0; glong items_read = 0; glong items_written = 0; GError *error = NULL; gunichar2 *unicodestr = NULL; //check for valid input if (!plist || !plist_bin || *plist_bin || !length) return; //list of objects objects = g_ptr_array_new(); //hashtable to write only once same nodes ref_table = g_hash_table_new(plist_data_hash, plist_data_compare); //serialize plist ser_s.objects = objects; ser_s.ref_table = ref_table; serialize_plist(plist, &ser_s); //now stream to output buffer offset_size = 0; //unknown yet dict_param_size = get_needed_bytes(objects->len); num_objects = objects->len; root_object = 0; //root is first in list offset_table_index = 0; //unknown yet //setup a dynamic bytes array to store bplist in bplist_buff = g_byte_array_new(); //set magic number and version g_byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); g_byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); //write objects and table offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t)); for (i = 0; i < num_objects; i++) { plist_data_t data = plist_get_data(g_ptr_array_index(objects, i)); offsets[i] = bplist_buff->len; switch (data->type) { case PLIST_BOOLEAN: buff = (uint8_t *) malloc(sizeof(uint8_t)); buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE; g_byte_array_append(bplist_buff, buff, sizeof(uint8_t)); free(buff); break; case PLIST_UINT: write_int(bplist_buff, data->intval); break; case PLIST_REAL: write_real(bplist_buff, data->realval); break; case PLIST_KEY: case PLIST_STRING: len = strlen(data->strval); if ( is_ascii_string(data->strval, len) ) { write_string(bplist_buff, data->strval); } else { unicodestr = g_utf8_to_utf16(data->strval, len, &items_read, &items_written, &error); write_unicode(bplist_buff, unicodestr, items_written); g_free(unicodestr); } break; case PLIST_DATA: write_data(bplist_buff, data->buff, data->length); case PLIST_ARRAY: write_array(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); break; case PLIST_DICT: write_dict(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); break; case PLIST_DATE: write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / G_USEC_PER_SEC); break; default: break; } } //free intermediate objects g_hash_table_foreach_remove(ref_table, free_index, NULL); g_ptr_array_free(objects, TRUE); g_hash_table_destroy(ref_table); //write offsets offset_size = get_needed_bytes(bplist_buff->len); offset_table_index = bplist_buff->len; for (i = 0; i < num_objects; i++) { uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); #if G_BYTE_ORDER == G_BIG_ENDIAN offsets[i] = offsets[i] << ((sizeof(uint64_t) - offset_size) * 8); #endif memcpy(offsetbuff, &offsets[i], offset_size); byte_convert(offsetbuff, offset_size); g_byte_array_append(bplist_buff, offsetbuff, offset_size); free(offsetbuff); } //experimental pad to reflect apple's files g_byte_array_append(bplist_buff, pad, 6); //setup trailer num_objects = GUINT64_FROM_BE(num_objects); root_object = GUINT64_FROM_BE(root_object); offset_table_index = GUINT64_FROM_BE(offset_table_index); memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t)); memcpy(trailer + BPLIST_TRL_PARMSIZE_IDX, &dict_param_size, sizeof(uint8_t)); memcpy(trailer + BPLIST_TRL_NUMOBJ_IDX, &num_objects, sizeof(uint64_t)); memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t)); memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t)); g_byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); //duplicate buffer *plist_bin = (char *) malloc(bplist_buff->len); memcpy(*plist_bin, bplist_buff->data, bplist_buff->len); *length = bplist_buff->len; g_byte_array_free(bplist_buff, TRUE); free(offsets); }