ffi, kerberos

D

Daniel Berger

Hi,

I'm trying to wrap two function calls from kerberos, krb5_init_context
and krb5_free_context. Here are the prototypes for both:

krb5_init_context(krb5_context * context) => krb5_error_code
krb5_free_context(krb5_context context) => void

krb5_context is a struct, but unfortunately I don't know what its
members are.

From the docs:

The krb5_context structure is designed to hold all per thread
state. All
global variables that are context specific are stored in this
structure,
including default encryption types, credentials-cache (ticket
file), and
default realms.

The internals of the structure should never be accessed directly,
func-
tions exist for extracting information.

All I know is that it's 8 bytes in size.

I tried something like this, but it didn't work:

require 'ffi'

module Krb5
class Context
extend FFI::Library

class Error < StandardError; end

ffi_lib 'krb5'

attach_function :krb5_init_context, [:string], :uint
attach_function :krb5_free_context, [:string], :void

def initialize
@ctx = FFI::MemoryPointer.new:)pointer, 8)
ret = krb5_init_context(@ctx)

if ret > 0
raise Error, "krb5_init_context() failed"
end

if block_given?
begin
yield self
ensure
free
end
end
end

def free
krb5_free_context(@ctx)
end
end
end

k = Krb5::Context.new
k.free

I can use a plain string buffer, but then it segfaults on the 'free'
call.

Any suggestions?

Thanks,

Dan
 
D

Daniel Berger

Hi,

I'm trying to wrap two function calls from kerberos, krb5_init_context
and krb5_free_context. Here are the prototypes for both:

krb5_init_context(krb5_context * context) =3D> krb5_error_code
krb5_free_context(krb5_context context) =3D> void

krb5_context is a struct, but unfortunately I don't know what its
members are.

From the docs:

=A0 =A0 =A0The krb5_context structure is designed to hold all per thread
state. All
=A0 =A0 =A0global variables that are context specific are stored in this
structure,
=A0 =A0 =A0including default encryption types, credentials-cache (ticket
file), and
=A0 =A0 =A0default realms.

=A0 =A0 =A0The internals of the structure should never be accessed direct= ly,
func-
=A0 =A0 =A0tions exist for extracting information.

All I know is that it's 8 bytes in size.

I tried something like this, but it didn't work:

require 'ffi'

module Krb5
=A0 class Context
=A0 =A0 extend FFI::Library

=A0 =A0 class Error < StandardError; end

=A0 =A0 ffi_lib 'krb5'

=A0 =A0 attach_function :krb5_init_context, [:string], :uint
=A0 =A0 attach_function :krb5_free_context, [:string], :void

=A0 =A0 def initialize
=A0 =A0 =A0 @ctx =3D FFI::MemoryPointer.new:)pointer, 8)
=A0 =A0 =A0 ret =3D krb5_init_context(@ctx)

=A0 =A0 =A0 if ret > 0
=A0 =A0 =A0 =A0 raise Error, "krb5_init_context() failed"
=A0 =A0 =A0 end

=A0 =A0 =A0 if block_given?
=A0 =A0 =A0 =A0 begin
=A0 =A0 =A0 =A0 =A0 yield self
=A0 =A0 =A0 =A0 ensure
=A0 =A0 =A0 =A0 =A0 free
=A0 =A0 =A0 =A0 end
=A0 =A0 =A0 end
=A0 =A0 end

=A0 =A0 def free
=A0 =A0 =A0 krb5_free_context(@ctx)
=A0 =A0 end
=A0 end
end

k =3D Krb5::Context.new
k.free

I can use a plain string buffer, but then it segfaults on the 'free'
call.

Any suggestions?

Oops, here's an updated version, but it segfaults on the 'free' call:

require 'ffi'

module Krb5
class Context
extend FFI::Library

class Error < StandardError; end

ffi_lib 'krb5'

attach_function :krb5_init_context, [:pointer], :uint
attach_function :krb5_free_context, [:pointer], :void

def initialize
@ctx =3D FFI::MemoryPointer.new:)char, 8)
ret =3D krb5_init_context(@ctx)

if ret > 0
raise Error, "krb5_init_context() failed"
end

if block_given?
begin
yield self
ensure
free
end
end
end

def free
krb5_free_context(@ctx)
end
end
end

k =3D Krb5::Context.new
k.free
 
S

Shawn Anderson

[Note: parts of this message were removed to make it a legal post.]

You may want to post this to the ruby-ffi mailing list.

/Shawn

Hi,

I'm trying to wrap two function calls from kerberos, krb5_init_context
and krb5_free_context. Here are the prototypes for both:

krb5_init_context(krb5_context * context) => krb5_error_code
krb5_free_context(krb5_context context) => void

krb5_context is a struct, but unfortunately I don't know what its
members are.

From the docs:

The krb5_context structure is designed to hold all per thread
state. All
global variables that are context specific are stored in this
structure,
including default encryption types, credentials-cache (ticket
file), and
default realms.

The internals of the structure should never be accessed directly,
func-
tions exist for extracting information.

All I know is that it's 8 bytes in size.

I tried something like this, but it didn't work:

require 'ffi'

module Krb5
class Context
extend FFI::Library

class Error < StandardError; end

ffi_lib 'krb5'

attach_function :krb5_init_context, [:string], :uint
attach_function :krb5_free_context, [:string], :void

def initialize
@ctx = FFI::MemoryPointer.new:)pointer, 8)
ret = krb5_init_context(@ctx)

if ret > 0
raise Error, "krb5_init_context() failed"
end

if block_given?
begin
yield self
ensure
free
end
end
end

def free
krb5_free_context(@ctx)
end
end
end

k = Krb5::Context.new
k.free

I can use a plain string buffer, but then it segfaults on the 'free'
call.

Any suggestions?

Oops, here's an updated version, but it segfaults on the 'free' call:

require 'ffi'

module Krb5
class Context
extend FFI::Library

class Error < StandardError; end

ffi_lib 'krb5'

attach_function :krb5_init_context, [:pointer], :uint
attach_function :krb5_free_context, [:pointer], :void

def initialize
@ctx = FFI::MemoryPointer.new:)char, 8)
ret = krb5_init_context(@ctx)

if ret > 0
raise Error, "krb5_init_context() failed"
end

if block_given?
begin
yield self
ensure
free
end
end
end

def free
krb5_free_context(@ctx)
end
end
end

k = Krb5::Context.new
k.free
 
H

Heesob Park

Hi,

2010/1/13 Daniel Berger said:
Hi,

I'm trying to wrap two function calls from kerberos, krb5_init_context
and krb5_free_context. Here are the prototypes for both:

krb5_init_context(krb5_context * context) =3D> krb5_error_code
krb5_free_context(krb5_context context) =3D> void

krb5_context is a struct, but unfortunately I don't know what its
members are.

From the docs:

=C2=A0 =C2=A0 The krb5_context structure is designed to hold all per thre= ad
state. All
=C2=A0 =C2=A0 global variables that are context specific are stored in th= is
structure,
=C2=A0 =C2=A0 including default encryption types, credentials-cache (tick= et
file), and
=C2=A0 =C2=A0 default realms.

=C2=A0 =C2=A0 The internals of the structure should never be accessed dir= ectly,
func-
=C2=A0 =C2=A0 tions exist for extracting information.

All I know is that it's 8 bytes in size.

I tried something like this, but it didn't work:

require 'ffi'

module Krb5
=C2=A0class Context
=C2=A0 =C2=A0extend FFI::Library

=C2=A0 =C2=A0class Error < StandardError; end

=C2=A0 =C2=A0ffi_lib 'krb5'

=C2=A0 =C2=A0attach_function :krb5_init_context, [:string], :uint
=C2=A0 =C2=A0attach_function :krb5_free_context, [:string], :void

=C2=A0 =C2=A0def initialize
=C2=A0 =C2=A0 =C2=A0@ctx =3D FFI::MemoryPointer.new:)pointer, 8)
=C2=A0 =C2=A0 =C2=A0ret =3D krb5_init_context(@ctx)

=C2=A0 =C2=A0 =C2=A0if ret > 0
=C2=A0 =C2=A0 =C2=A0 =C2=A0raise Error, "krb5_init_context() failed"
=C2=A0 =C2=A0 =C2=A0end

=C2=A0 =C2=A0 =C2=A0if block_given?
=C2=A0 =C2=A0 =C2=A0 =C2=A0begin
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0yield self
=C2=A0 =C2=A0 =C2=A0 =C2=A0ensure
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0free
=C2=A0 =C2=A0 =C2=A0 =C2=A0end
=C2=A0 =C2=A0 =C2=A0end
=C2=A0 =C2=A0end

=C2=A0 =C2=A0def free
=C2=A0 =C2=A0 =C2=A0krb5_free_context(@ctx)
=C2=A0 =C2=A0end
=C2=A0end
end

k =3D Krb5::Context.new
k.free

I can use a plain string buffer, but then it segfaults on the 'free'
call.

Any suggestions?

In my test platform, sizeof(krb5_context) is 4.
Here is a working code:

require 'ffi'

module Krb5
class Context
extend FFI::Library

class Error < StandardError; end

ffi_lib 'krb5'

attach_function :krb5_init_context, [:pointer], :uint
attach_function :krb5_free_context, [:uint], :void

def initialize
ptr =3D FFI::MemoryPointer.new:)char, 4)
ret =3D krb5_init_context(ptr)
if ret > 0
raise Error, "krb5_init_context() failed"
end
@ctx =3D ptr.read_int

if block_given?
begin
yield self
ensure
free
end
end
end

def free
krb5_free_context(@ctx)
end
end
end

k =3D Krb5::Context.new
k.free


Regards,

Park Heesob
 
D

Daniel Berger

Hi,

2010/1/13 Daniel Berger <[email protected]>:


I'm trying to wrap two function calls from kerberos, krb5_init_context
and krb5_free_context. Here are the prototypes for both:
krb5_init_context(krb5_context * context) =3D> krb5_error_code
krb5_free_context(krb5_context context) =3D> void
krb5_context is a struct, but unfortunately I don't know what its
members are.
From the docs:
=A0 =A0 The krb5_context structure is designed to hold all per thread
state. All
=A0 =A0 global variables that are context specific are stored in this
structure,
=A0 =A0 including default encryption types, credentials-cache (ticket
file), and
=A0 =A0 default realms.
=A0 =A0 The internals of the structure should never be accessed directl= y,
func-
=A0 =A0 tions exist for extracting information.
All I know is that it's 8 bytes in size.
I tried something like this, but it didn't work:
require 'ffi'
module Krb5
=A0class Context
=A0 =A0extend FFI::Library
=A0 =A0class Error < StandardError; end
=A0 =A0ffi_lib 'krb5'
=A0 =A0attach_function :krb5_init_context, [:string], :uint
=A0 =A0attach_function :krb5_free_context, [:string], :void
=A0 =A0def initialize
=A0 =A0 =A0@ctx =3D FFI::MemoryPointer.new:)pointer, 8)
=A0 =A0 =A0ret =3D krb5_init_context(@ctx)
=A0 =A0 =A0if ret > 0
=A0 =A0 =A0 =A0raise Error, "krb5_init_context() failed"
=A0 =A0 =A0end
=A0 =A0 =A0if block_given?
=A0 =A0 =A0 =A0begin
=A0 =A0 =A0 =A0 =A0yield self
=A0 =A0 =A0 =A0ensure
=A0 =A0 =A0 =A0 =A0free
=A0 =A0 =A0 =A0end
=A0 =A0 =A0end
=A0 =A0end
=A0 =A0def free
=A0 =A0 =A0krb5_free_context(@ctx)
=A0 =A0end
=A0end
end
k =3D Krb5::Context.new
k.free
I can use a plain string buffer, but then it segfaults on the 'free'
call.
Any suggestions?

In my test platform, sizeof(krb5_context) is 4.
Here is a working code:

require 'ffi'

module Krb5
=A0class Context
=A0 =A0extend FFI::Library

=A0 =A0class Error < StandardError; end

=A0 =A0ffi_lib 'krb5'

=A0 =A0attach_function :krb5_init_context, [:pointer], :uint
=A0 =A0attach_function :krb5_free_context, [:uint], :void

=A0 =A0def initialize
=A0 =A0 =A0ptr =3D FFI::MemoryPointer.new:)char, 4)
=A0 =A0 =A0ret =3D krb5_init_context(ptr)
=A0 =A0 =A0if ret > 0
=A0 =A0 =A0 =A0raise Error, "krb5_init_context() failed"
=A0 =A0 =A0end
=A0 =A0 =A0@ctx =3D ptr.read_int

=A0 =A0 =A0if block_given?
=A0 =A0 =A0 =A0begin
=A0 =A0 =A0 =A0 =A0yield self
=A0 =A0 =A0 =A0ensure
=A0 =A0 =A0 =A0 =A0free
=A0 =A0 =A0 =A0end
=A0 =A0 =A0end
=A0 =A0end

=A0 =A0def free
=A0 =A0 =A0krb5_free_context(@ctx)
=A0 =A0end
=A0end
end

k =3D Krb5::Context.new
k.free

This almost got me there. I had to modify it somewhat to account for
the fact that I'm on Snow Leopard (x64), so I replaced :uint
with :long, 4 with 8 and ptr.read_int with ptr.read_long.

Now I need to figure out how to create an FFI::MemoryPointer without
necessarily knowing the size of the first argument.

Thanks for the help!

Regards,

Dan
 
L

Luc Heinrich

Now I need to figure out how to create an FFI::MemoryPointer without
necessarily knowing the size of the first argument.

The one bit you are missing here is that krb5_context is not a struct. =
It's a *pointer* to a struct as can be seen in krb5/krb5.h:

typedef struct _krb5_context * krb5_context;

If krb5_context was a struct you wouldn't be able to do this in C:

krb5_context ctx;
krb5_init_context(&ctx);

Because event the C compiler would not know how to statically allocate =
without knowing the size of the struct. I assure you that it would =
complain :)

So, with that in mind you can now simply completely ignore the size of =
the struct and only use pointers. Like this:

module FFI::Krb5
extend FFI::Library
ffi_lib "krb5"
=20
attach_function :krb5_init_context, [:buffer_out], :uint
attach_function :krb5_free_context, [:pointer], :void
end

What you pass to krb5_init_context is really a pointer to a pointer. You =
can now use that this way:

buf =3D FFI::Buffer.new:)pointer)
res =3D FFI::Krb5.krb5_init_context(buf)
puts res

First you allocate a buffer which will contain a pointer (the =
krb5_context, which is, you get it now, a pointer :)), and then you pass =
this buffer to the krb5_init_context. But now you will probably want to =
*use* this context so you first have to get it out of the buffer, like =
this:

ctx =3D buf.get_pointer(0)

Which allows you to use it in any other krb5_* call, like the =
krb5_free_context which we have defined:

FFI::Krb5.krb5_free_context(ptr)

--=20
Luc Heinrich - (e-mail address removed)
 
D

Daniel Berger

Luc said:
The one bit you are missing here is that krb5_context is not a struct. It=
's a *pointer* to a struct as can be seen in krb5/krb5.h:
typedef struct _krb5_context * krb5_context;

If krb5_context was a struct you wouldn't be able to do this in C:

krb5_context ctx;
krb5_init_context(&ctx);

Because event the C compiler would not know how to statically allocate wi=
thout knowing the size of the struct. I assure you that it would complain :=
)
So, with that in mind you can now simply completely ignore the size of th=
e struct and only use pointers. Like this:
module FFI::Krb5
extend FFI::Library
ffi_lib "krb5"

attach_function :krb5_init_context, [:buffer_out], :uint
attach_function :krb5_free_context, [:pointer], :void
end

What you pass to krb5_init_context is really a pointer to a pointer. You = can now use that this way:

buf =3D FFI::Buffer.new:)pointer)
res =3D FFI::Krb5.krb5_init_context(buf)
puts res

First you allocate a buffer which will contain a pointer (the krb5_contex=
t, which is, you get it now, a pointer :)), and then you pass this buffer t=
o the krb5_init_context. But now you will probably want to *use* this conte=
xt so you first have to get it out of the buffer, like this:
ctx =3D buf.get_pointer(0)

Which allows you to use it in any other krb5_* call, like the krb5_free_c= ontext which we have defined:

FFI::Krb5.krb5_free_context(ptr)

Thank you. This was very helpful.

Regards,

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top