static void release_op_data (void *hook) { op_data_t opd = (op_data_t) hook; gpgme_signature_t sig = opd->result.signatures; while (sig) { gpgme_signature_t next = sig->next; gpgme_sig_notation_t notation = sig->notations; while (notation) { gpgme_sig_notation_t next_nota = notation->next; _gpgme_sig_notation_free (notation); notation = next_nota; } if (sig->fpr) free (sig->fpr); if (sig->pka_address) free (sig->pka_address); release_tofu_info (sig->tofu); free (sig); sig = next; } if (opd->result.file_name) free (opd->result.file_name); }
/* Clear all notation data from the context. */ void _gpgme_sig_notation_clear (gpgme_ctx_t ctx) { gpgme_sig_notation_t notation; if (!ctx) return; notation = ctx->sig_notations; while (notation) { gpgme_sig_notation_t next_notation = notation->next; _gpgme_sig_notation_free (notation); notation = next_notation; } ctx->sig_notations = NULL; }
/* Create a new, empty signature notation data object. */ gpgme_error_t _gpgme_sig_notation_create(gpgme_sig_notation_t *notationp, const char *name, int name_len, const char *value, int value_len, gpgme_sig_notation_flags_t flags) { gpgme_error_t err = 0; gpgme_sig_notation_t notation; /* Currently, we require all notations to be human-readable. */ if(name && !(flags & GPGME_SIG_NOTATION_HUMAN_READABLE)) return gpg_error(GPG_ERR_INV_VALUE); notation = calloc(1, sizeof(*notation)); if(!notation) return gpg_error_from_errno(errno); /* This is critical. We want to reliably identify policy URLs by using a NULL pointer for NAME. So all notations must have a NAME string, even if it is empty. */ if(name) { /* We add a trailing '\0' for stringification in the good case. */ notation->name = malloc(name_len + 1); if(!notation->name) { err = gpg_error_from_errno(errno); goto err; } memcpy(notation->name, name, name_len); notation->name[name_len] = '\0'; notation->name_len = name_len; } if(value) { /* We add a trailing '\0' for stringification in the good case. */ notation->value = malloc(value_len + 1); if(!notation->value) { err = gpg_error_from_errno(errno); goto err; } memcpy(notation->value, value, value_len); notation->value[value_len] = '\0'; notation->value_len = value_len; } sig_notation_set_flags(notation, flags); *notationp = notation; return 0; err: _gpgme_sig_notation_free(notation); return err; }
static gpgme_error_t parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args) { gpgme_error_t err; gpgme_sig_notation_t *lastp = &sig->notations; gpgme_sig_notation_t notation = sig->notations; char *p; if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL) { p = strchr (args, ' '); if (p) *p = '\0'; /* FIXME: We could keep a pointer to the last notation in the list. */ while (notation && notation->value) { lastp = ¬ation->next; notation = notation->next; } if (notation) /* There is another notation name without data for the previous one. The crypto backend misbehaves. */ return trace_gpg_error (GPG_ERR_INV_ENGINE); err = _gpgme_sig_notation_create (¬ation, NULL, 0, NULL, 0, 0); if (err) return err; if (code == GPGME_STATUS_NOTATION_NAME) { err = _gpgme_decode_percent_string (args, ¬ation->name, 0, 0); if (err) { _gpgme_sig_notation_free (notation); return err; } notation->name_len = strlen (notation->name); /* Set default flags for use with older gpg versions which * do not emit a NOTATIONS_FLAG line. */ notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE; notation->human_readable = 1; } else { /* This is a policy URL. */ err = _gpgme_decode_percent_string (args, ¬ation->value, 0, 0); if (err) { _gpgme_sig_notation_free (notation); return err; } notation->value_len = strlen (notation->value); } *lastp = notation; } else if (code == GPGME_STATUS_NOTATION_FLAGS) { char *field[2]; while (notation && notation->next) { lastp = ¬ation->next; notation = notation->next; } if (!notation || !notation->name) { /* There are notation flags without a previous notation name. * The crypto backend misbehaves. */ return trace_gpg_error (GPG_ERR_INV_ENGINE); } if (_gpgme_split_fields (args, field, DIM (field)) < 2) { /* Required args missing. */ return trace_gpg_error (GPG_ERR_INV_ENGINE); } notation->flags = 0; if (atoi (field[0])) { notation->flags |= GPGME_SIG_NOTATION_CRITICAL; notation->critical = 1; } if (atoi (field[1])) { notation->flags |= GPGME_SIG_NOTATION_HUMAN_READABLE; notation->human_readable = 1; } } else if (code == GPGME_STATUS_NOTATION_DATA) { int len = strlen (args) + 1; char *dest; /* FIXME: We could keep a pointer to the last notation in the list. */ while (notation && notation->next) { lastp = ¬ation->next; notation = notation->next; } if (!notation || !notation->name) /* There is notation data without a previous notation name. The crypto backend misbehaves. */ return trace_gpg_error (GPG_ERR_INV_ENGINE); if (!notation->value) { dest = notation->value = malloc (len); if (!dest) return gpg_error_from_syserror (); } else { int cur_len = strlen (notation->value); dest = realloc (notation->value, len + strlen (notation->value)); if (!dest) return gpg_error_from_syserror (); notation->value = dest; dest += cur_len; } err = _gpgme_decode_percent_string (args, &dest, len, 0); if (err) return err; notation->value_len += strlen (dest); } else return trace_gpg_error (GPG_ERR_INV_ENGINE); return 0; }
static gpgme_error_t parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args) { gpgme_error_t err; gpgme_sig_notation_t *lastp = &sig->notations; gpgme_sig_notation_t notation = sig->notations; char *end = strchr (args, ' '); if (end) *end = '\0'; if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL) { /* FIXME: We could keep a pointer to the last notation in the list. */ while (notation && notation->value) { lastp = ¬ation->next; notation = notation->next; } if (notation) /* There is another notation name without data for the previous one. The crypto backend misbehaves. */ return gpg_error (GPG_ERR_INV_ENGINE); err = _gpgme_sig_notation_create (¬ation, NULL, 0, NULL, 0, 0); if (err) return err; if (code == GPGME_STATUS_NOTATION_NAME) { err = _gpgme_decode_percent_string (args, ¬ation->name, 0, 0); if (err) { _gpgme_sig_notation_free (notation); return err; } notation->name_len = strlen (notation->name); /* FIXME: For now we fake the human-readable flag. The critical flag can not be reported as it is not provided. */ notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE; notation->human_readable = 1; } else { /* This is a policy URL. */ err = _gpgme_decode_percent_string (args, ¬ation->value, 0, 0); if (err) { _gpgme_sig_notation_free (notation); return err; } notation->value_len = strlen (notation->value); } *lastp = notation; } else if (code == GPGME_STATUS_NOTATION_DATA) { int len = strlen (args) + 1; char *dest; /* FIXME: We could keep a pointer to the last notation in the list. */ while (notation && notation->next) { lastp = ¬ation->next; notation = notation->next; } if (!notation || !notation->name) /* There is notation data without a previous notation name. The crypto backend misbehaves. */ return gpg_error (GPG_ERR_INV_ENGINE); if (!notation->value) { dest = notation->value = malloc (len); if (!dest) return gpg_error_from_errno (errno); } else { int cur_len = strlen (notation->value); dest = realloc (notation->value, len + strlen (notation->value)); if (!dest) return gpg_error_from_errno (errno); notation->value = dest; dest += cur_len; } err = _gpgme_decode_percent_string (args, &dest, len, 0); if (err) return err; notation->value_len += strlen (dest); } else return gpg_error (GPG_ERR_INV_ENGINE); return 0; }