Skip to content

Commit

Permalink
Add the ignore_mdc_error flag setter and getter
Browse files Browse the repository at this point in the history
Add generic `get_ctx_flag` getter and `set_ctx_flag` setter
  • Loading branch information
Verseth authored and ueno committed Jan 23, 2024
1 parent fb4c588 commit 2ac00ff
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ coverage
Gemfile.lock
/tmp/*
/ports/*
.byebug_history
84 changes: 84 additions & 0 deletions ext/gpgme/gpgme_n.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,46 @@ rb_s_gpgme_release (VALUE dummy, VALUE vctx)
return Qnil;
}

static VALUE
rb_s_gpgme_set_ctx_flag (VALUE dummy, VALUE vctx, VALUE vname, VALUE vstr)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
char* name;
char* str;

name = StringValueCStr(vname);
str = StringValueCStr(vstr);

UNWRAP_GPGME_CTX(vctx, ctx);
if (!ctx)
rb_raise (rb_eArgError, "released ctx");

err = gpgme_set_ctx_flag(ctx, name, str);
return LONG2NUM(err);
}

static VALUE
rb_s_gpgme_get_ctx_flag (VALUE dummy, VALUE vctx, VALUE vname)
{
gpgme_ctx_t ctx;
const char* name;
int yes;

name = StringValueCStr(vname);

UNWRAP_GPGME_CTX(vctx, ctx);
if (!ctx)
rb_raise (rb_eArgError, "released ctx");

const char* result;
result = gpgme_get_ctx_flag(ctx, name);
if (result == NULL)
rb_raise (rb_eArgError, "incorrect ctx flag name");

return rb_str_new_cstr(result);
}

static VALUE
rb_s_gpgme_set_protocol (VALUE dummy, VALUE vctx, VALUE vproto)
{
Expand Down Expand Up @@ -566,6 +606,42 @@ rb_s_gpgme_get_armor (VALUE dummy, VALUE vctx)
return INT2FIX(yes);
}

static VALUE
rb_s_gpgme_set_ignore_mdc_error (VALUE dummy, VALUE vctx, VALUE vyes)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
int yes;

yes = NUM2INT(vyes);

UNWRAP_GPGME_CTX(vctx, ctx);
if (!ctx)
rb_raise (rb_eArgError, "released ctx");

err = gpgme_set_ctx_flag(ctx, "ignore-mdc-error", yes ? "1" : "");
return LONG2NUM(err);
}

static VALUE
rb_s_gpgme_get_ignore_mdc_error (VALUE dummy, VALUE vctx)
{
gpgme_ctx_t ctx;
int yes;

UNWRAP_GPGME_CTX(vctx, ctx);
if (!ctx)
rb_raise (rb_eArgError, "released ctx");

const char* result;
result = gpgme_get_ctx_flag(ctx, "ignore-mdc-error");
if (result == NULL)
rb_raise (rb_eArgError, "incorrect ctx flag name");

yes = (result && *result)? !!atoi (result) : 0;
return INT2FIX(yes);
}

static VALUE
rb_s_gpgme_set_textmode (VALUE dummy, VALUE vctx, VALUE vyes)
{
Expand Down Expand Up @@ -2373,6 +2449,10 @@ Init_gpgme_n (void)
rb_s_gpgme_release, 1);

/* Context Attributes */
rb_define_module_function (mGPGME, "gpgme_set_ctx_flag",
rb_s_gpgme_set_ctx_flag, 3);
rb_define_module_function (mGPGME, "gpgme_get_ctx_flag",
rb_s_gpgme_get_ctx_flag, 2);
rb_define_module_function (mGPGME, "gpgme_set_protocol",
rb_s_gpgme_set_protocol, 2);
rb_define_module_function (mGPGME, "gpgme_get_protocol",
Expand All @@ -2381,6 +2461,10 @@ Init_gpgme_n (void)
rb_s_gpgme_set_armor, 2);
rb_define_module_function (mGPGME, "gpgme_get_armor",
rb_s_gpgme_get_armor, 1);
rb_define_module_function (mGPGME, "gpgme_set_ignore_mdc_error",
rb_s_gpgme_set_ignore_mdc_error, 2);
rb_define_module_function (mGPGME, "gpgme_get_ignore_mdc_error",
rb_s_gpgme_get_ignore_mdc_error, 1);
rb_define_module_function (mGPGME, "gpgme_set_textmode",
rb_s_gpgme_set_textmode, 2);
rb_define_module_function (mGPGME, "gpgme_get_textmode",
Expand Down
66 changes: 60 additions & 6 deletions lib/gpgme/ctx.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ def self.new(options = {})
raise exc if exc
ctx = rctx[0]

ctx.protocol = options[:protocol] if options[:protocol]
ctx.armor = options[:armor] if options[:armor]
ctx.textmode = options[:textmode] if options[:textmode]
ctx.keylist_mode = options[:keylist_mode] if options[:keylist_mode]
ctx.pinentry_mode = options[:pinentry_mode] if options[:pinentry_mode]
ctx.offline = options[:offline] if options[:offline]
ctx.protocol = options[:protocol] if options[:protocol]
ctx.armor = options[:armor] if options[:armor]
ctx.textmode = options[:textmode] if options[:textmode]
ctx.keylist_mode = options[:keylist_mode] if options[:keylist_mode]
ctx.pinentry_mode = options[:pinentry_mode] if options[:pinentry_mode]
ctx.offline = options[:offline] if options[:offline]
ctx.ignore_mdc_error = options[:ignore_mdc_error] if options[:ignore_mdc_error]

if options[:password]
ctx.set_passphrase_callback GPGME::Ctx.method(:pass_function),
Expand Down Expand Up @@ -103,6 +104,43 @@ def release
# Getters and setters
##

# Get the value of the Ctx flag with the given name.
#
# Allowed flag names may include:
# - 'redraw'
# - 'full-status'
# - 'raw-description'
# - 'export-session-key'
# - 'override-session-key'
# - 'include-key-block'
# - 'auto-key-import'
# - 'auto-key-retrieve'
# - 'request-origin'
# - 'no-symkey-cache'
# - 'ignore-mdc-error'
# - 'auto-key-locate'
# - 'trust-model'
# - 'extended-edit'
# - 'cert-expire'
# - 'key-origin'
# - 'import-filter'
# - 'no-auto-check-trustdb'
#
# Please consult the GPGPME documentation for more details
#
def get_ctx_flag(flag_name)
GPGME::gpgme_get_ctx_flag(self, flag_name.to_s)
end

# Set the Ctx flag with the given name
# to the given value.
def set_ctx_flag(flag_name, val)
err = GPGME::gpgme_set_ctx_flag(self, flag_name.to_s, val.to_s)
exc = GPGME::error_to_exception(err)
raise exc if exc
val
end

# Set the +protocol+ used within this context. See {GPGME::Ctx.new} for
# possible values.
def protocol=(proto)
Expand All @@ -128,6 +166,22 @@ def armor
GPGME::gpgme_get_armor(self) == 1 ? true : false
end

# This option ignores a MDC integrity protection failure.
# It is required to decrypt old messages which did not use an MDC.
# It may also be useful if a message is partially garbled,
# but it is necessary to get as much data as possible out of that garbled message.
# Be aware that a missing or failed MDC can be an indication of an attack.
# Use with great caution.
def ignore_mdc_error=(yes)
GPGME::gpgme_set_ignore_mdc_error(self, yes ? 1 : 0)
yes
end

# Return true if the MDC integrity protection is disabled.
def ignore_mdc_error
GPGME::gpgme_get_ignore_mdc_error(self) == 1 ? true : false
end

# Tell whether canonical text mode should be used.
def textmode=(yes)
GPGME::gpgme_set_textmode(self, yes ? 1 : 0)
Expand Down
124 changes: 124 additions & 0 deletions test/ctx_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,70 @@
end
end

describe :get_ctx_flag do
it "reads flags with getters and setters" do
ctx = GPGME::Ctx.new

refute ctx.ignore_mdc_error
assert_equal "", ctx.get_ctx_flag("ignore-mdc-error")

ctx.ignore_mdc_error = true

assert ctx.ignore_mdc_error
assert_equal "1", ctx.get_ctx_flag("ignore-mdc-error")
end

it "can get flags without getters and setters" do
ctx = GPGME::Ctx.new

assert_equal "", ctx.get_ctx_flag("auto-key-locate")
ctx.set_ctx_flag("auto-key-locate", "cert")
assert_equal "cert", ctx.get_ctx_flag("auto-key-locate")
end

it "raises an error when a flag doesn't exist" do
ctx = GPGME::Ctx.new

assert_raises ArgumentError do
ctx.get_ctx_flag("foo")
end
end
end

describe :set_ctx_flag do
it "sets the value for a flag with a getter" do
ctx = GPGME::Ctx.new
refute ctx.ignore_mdc_error

ctx.set_ctx_flag("ignore-mdc-error", "1")
assert ctx.ignore_mdc_error
end

it "unsets the value for a flag with a getter" do
ctx = GPGME::Ctx.new(ignore_mdc_error: true)
assert ctx.ignore_mdc_error

ctx.set_ctx_flag("ignore-mdc-error", "0")
refute ctx.ignore_mdc_error
end

it "can set flags without getters and setters" do
ctx = GPGME::Ctx.new

assert_equal "", ctx.get_ctx_flag("auto-key-locate")
ctx.set_ctx_flag("auto-key-locate", "cert")
assert_equal "cert", ctx.get_ctx_flag("auto-key-locate")
end

it "raises an error when a flag doesn't exist" do
ctx = GPGME::Ctx.new

assert_raises GPGME::Error do
ctx.set_ctx_flag("foo", "bar")
end
end
end

describe :armor do
it "sets false by default" do
ctx = GPGME::Ctx.new
Expand All @@ -101,6 +165,66 @@
end
end

describe :ignore_mdc_error do
it "sets false by default" do
ctx = GPGME::Ctx.new
refute ctx.ignore_mdc_error
end

it "can set" do
ctx = GPGME::Ctx.new
ctx.ignore_mdc_error = true
assert ctx.ignore_mdc_error
end

it "can set and unset" do
ctx = GPGME::Ctx.new

ctx.ignore_mdc_error = true
assert ctx.ignore_mdc_error

ctx.ignore_mdc_error = false
refute ctx.ignore_mdc_error
end

it "can set and get in constructor" do
ctx = GPGME::Ctx.new(:ignore_mdc_error => false)
refute ctx.ignore_mdc_error
ctx = GPGME::Ctx.new(:ignore_mdc_error => true)
assert ctx.ignore_mdc_error
end
end

describe :ignore_mdc_error do
it "sets false by default" do
ctx = GPGME::Ctx.new
refute ctx.ignore_mdc_error
end

it "can set" do
ctx = GPGME::Ctx.new

ctx.ignore_mdc_error = true
assert ctx.ignore_mdc_error
end

it "can unset" do
ctx = GPGME::Ctx.new(ignore_mdc_error: true)
assert ctx.ignore_mdc_error

ctx.ignore_mdc_error = false
refute ctx.ignore_mdc_error
end

it "can set and get in constructor" do
ctx = GPGME::Ctx.new(:ignore_mdc_error => false)
refute ctx.ignore_mdc_error

ctx = GPGME::Ctx.new(:ignore_mdc_error => true)
assert ctx.ignore_mdc_error
end
end

describe :protocol do
it "sets 0 by default" do
ctx = GPGME::Ctx.new
Expand Down

0 comments on commit 2ac00ff

Please sign in to comment.