static gboolean parse_v4_signature_subpackets (const guchar **at, const guchar *end, GcrRecord *record, SigSubpacket *subpkt) { gsize length; guint8 sub_type; const guchar *stop; while (*at != end) { if (!read_new_length (at, end, &length) || !read_byte (at, end, &sub_type) || length == 0) return FALSE; /* The length includes the sub_type */ length--; stop = *at + length; if (stop > end) return FALSE; /* Actually parse the sub packets */ if (!parse_v4_signature_subpacket (at, stop, sub_type, record, subpkt)) return FALSE; if (*at != stop) return FALSE; } return TRUE; }
static gboolean parse_user_attribute (const guchar *beg, const guchar **at, const guchar *end, GcrOpenpgpParseFlags flags, GPtrArray *records) { gsize subpkt_len; guint count = 0; const guchar *start; const guchar *subpkt_beg; guint8 subpkt_type; gchar *fingerprint; gchar *string; GcrRecord *record; start = *at; while (*at != end) { subpkt_beg = *at; if (!read_new_length (at, end, &subpkt_len) || !read_byte (at, end, &subpkt_type)) return FALSE; count++; if (flags & GCR_OPENPGP_PARSE_ATTRIBUTES) { if (!parse_user_attribute_packet (subpkt_beg, at, *at + (subpkt_len - 1), subpkt_type, records)) return FALSE; /* We already progressed one extra byte for the subpkt_type */ } else { *at += (subpkt_len - 1); } } fingerprint = hash_user_id_or_attribute (start, end); string = g_strdup_printf ("%d %d", count, (guint)(*at - start)); record = _gcr_record_new (GCR_RECORD_SCHEMA_UAT, GCR_RECORD_UAT_MAX, ':'); _gcr_record_take_raw (record, GCR_RECORD_UAT_FINGERPRINT, fingerprint); _gcr_record_take_raw (record, GCR_RECORD_UAT_COUNT_SIZE, string); g_ptr_array_add (records, record); return TRUE; }
static GcrDataError read_openpgp_packet (const guchar **at, const guchar *end, guint8 *pkt_type, gsize *length) { gboolean new_ctb; guint8 ctb; gboolean ret; if (!read_byte (at, end, &ctb)) return GCR_ERROR_UNRECOGNIZED; if (!(ctb & 0x80)) return GCR_ERROR_UNRECOGNIZED; /* RFC2440 packet format. */ if (ctb & 0x40) { *pkt_type = ctb & 0x3f; new_ctb = TRUE; /* the old RFC1991 packet format. */ } else { *pkt_type = ctb & 0x3f; *pkt_type >>= 2; new_ctb = FALSE; } if (*pkt_type > 63) return GCR_ERROR_UNRECOGNIZED; if (new_ctb) ret = read_new_length (at, end, length); else ret = read_old_length (at, end, ctb, length); if (!ret) return GCR_ERROR_UNRECOGNIZED; if ((*at) + *length > end) return GCR_ERROR_FAILURE; return GCR_SUCCESS; }
/** * cdk_pkt_read: * @inp: the input stream * @pkt: allocated packet handle to store the packet * * Parse the next packet on the @inp stream and return its contents in @pkt. **/ cdk_error_t cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt) { int ctb, is_newctb; int pkttype; size_t pktlen = 0, pktsize = 0, is_partial = 0; cdk_error_t rc; if (!inp || !pkt) return CDK_Inv_Value; ctb = cdk_stream_getc (inp); if (cdk_stream_eof (inp) || ctb == EOF) return CDK_EOF; else if (!ctb) return CDK_Inv_Packet; pktsize++; if (!(ctb & 0x80)) { _cdk_log_info ("cdk_pkt_read: no openpgp data found. " "(ctb=%02X; fpos=%02X)\n", ctb, cdk_stream_tell (inp)); return CDK_Inv_Packet; } if (ctb & 0x40) /* RFC2440 packet format. */ { pkttype = ctb & 0x3f; is_newctb = 1; } else /* the old RFC1991 packet format. */ { pkttype = ctb & 0x3f; pkttype >>= 2; is_newctb = 0; } if (pkttype > 63) { _cdk_log_info ("cdk_pkt_read: unknown type %d\n", pkttype); return CDK_Inv_Packet; } if (is_newctb) read_new_length (inp, &pktlen, &pktsize, &is_partial); else read_old_length (inp, ctb, &pktlen, &pktsize); pkt->pkttype = pkttype; pkt->pktlen = pktlen; pkt->pktsize = pktsize + pktlen; pkt->old_ctb = is_newctb ? 0 : 1; rc = 0; switch (pkt->pkttype) { case CDK_PKT_ATTRIBUTE: pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id + pkt->pktlen + 16 + 1); if (!pkt->pkt.user_id) return CDK_Out_Of_Core; pkt->pkt.user_id->name = (char*)pkt->pkt.user_id + sizeof(*pkt->pkt.user_id); rc = read_attribute (inp, pktlen, pkt->pkt.user_id); pkt->pkttype = CDK_PKT_ATTRIBUTE; break; case CDK_PKT_USER_ID: pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id + pkt->pktlen + 1); if (!pkt->pkt.user_id) return CDK_Out_Of_Core; pkt->pkt.user_id->name = (char*)pkt->pkt.user_id + sizeof(*pkt->pkt.user_id); rc = read_user_id (inp, pktlen, pkt->pkt.user_id); break; case CDK_PKT_PUBLIC_KEY: pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key); if (!pkt->pkt.public_key) return CDK_Out_Of_Core; rc = read_public_key (inp, pktlen, pkt->pkt.public_key); break; case CDK_PKT_PUBLIC_SUBKEY: pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key); if (!pkt->pkt.public_key) return CDK_Out_Of_Core; rc = read_public_subkey (inp, pktlen, pkt->pkt.public_key); break; case CDK_PKT_SECRET_KEY: pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key); if (!pkt->pkt.secret_key) return CDK_Out_Of_Core; pkt->pkt.secret_key->pk = cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk); if (!pkt->pkt.secret_key->pk) return CDK_Out_Of_Core; rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key); break; case CDK_PKT_SECRET_SUBKEY: pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key); if (!pkt->pkt.secret_key) return CDK_Out_Of_Core; pkt->pkt.secret_key->pk = cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk); if (!pkt->pkt.secret_key->pk) return CDK_Out_Of_Core; rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key); break; case CDK_PKT_LITERAL: pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal); if (!pkt->pkt.literal) return CDK_Out_Of_Core; rc = read_literal (inp, pktlen, &pkt->pkt.literal, is_partial); break; case CDK_PKT_ONEPASS_SIG: pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig); if (!pkt->pkt.onepass_sig) return CDK_Out_Of_Core; rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig); break; case CDK_PKT_SIGNATURE: pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature); if (!pkt->pkt.signature) return CDK_Out_Of_Core; rc = read_signature (inp, pktlen, pkt->pkt.signature); break; case CDK_PKT_PUBKEY_ENC: pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc); if (!pkt->pkt.pubkey_enc) return CDK_Out_Of_Core; rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc); break; case CDK_PKT_COMPRESSED: pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed); if (!pkt->pkt.compressed) return CDK_Out_Of_Core; rc = read_compressed (inp, pktlen, pkt->pkt.compressed); break; case CDK_PKT_MDC: pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc); if (!pkt->pkt.mdc) return CDK_Out_Of_Core; rc = read_mdc (inp, pkt->pkt.mdc); break; default: /* Skip all packets we don't understand */ skip_packet (inp, pktlen); break; } return rc; }