# Ffi, kerberos

**URL:** <https://www.ruby-forum.com/t/ffi-kerberos/181512>\
**Category:** Ruby\
**Created:** [January 12, 2010, 11:48pm UTC](https://www.ruby-forum.com/t/ffi-kerberos/181512 "2010-01-12T23:48:26Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 12, 2010, 11:48pm UTC](https://www.ruby-forum.com/t/ffi-kerberos/181512/1 "2010-01-12T23:48:26Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 13, 2010, 12:01am UTC](https://www.ruby-forum.com/t/ffi-kerberos/181512/2 "2010-01-13T00:01:18Z")

</div>

On Jan 12, 3:48 pm, Daniel B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> The internals of the structure should never be accessed directly,
> 
> ```
> 
> class Context  
> @ctx = FFI::MemoryPointer.new(:pointer, 8)  
> free  
> 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

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 13, 2010, 12:57am UTC](https://www.ruby-forum.com/t/ffi-kerberos/181512/3 "2010-01-13T00:57:29Z")

</div>

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

/Shawn

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 13, 2010, 2:52am UTC](https://www.ruby-forum.com/t/ffi-kerberos/181512/4 "2010-01-13T02:52:47Z")

</div>

Hi,

2010/1/13 Daniel B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Â Â The internals of the structure should never be accessed directly,  
> Â class Context  
> Â Â Â @ctx = FFI::MemoryPointer.new(:pointer, 8)  
> Â Â Â Â Â free  
> k = 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 = FFI::MemoryPointer.new(:char, 4)  
ret = krb5\_init\_context(ptr)  
if ret \> 0  
raise Error, “krb5\_init\_context() failed”  
end  
@ctx = ptr.read\_int

```
 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

Regards,

Park H.

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 13, 2010, 5:57pm UTC](https://www.ruby-forum.com/t/ffi-kerberos/181512/5 "2010-01-13T17:57:42Z")

</div>

On 13 janv. 2010, at 16:53, Daniel B. wrote:

> 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”

```
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 = FFI::Buffer.new(:pointer)  
res = 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 = 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)

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 13, 2010, 4:54pm UTC](https://www.ruby-forum.com/t/ffi-kerberos/181512/6 "2010-01-13T16:54:27Z")

</div>

On Jan 12, 6:52 pm, Heesob P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ```
> > global variables that are context specific are stored in this
> > 
> > ```
> 
> > ffi\_lib ‘krb5’  
> > end  
> > def free
> 
> ```
> if ret > 0
> end
> 
> ```
> 
> end
> 
> def free  
> krb5\_free\_context(@ctx)  
> end  
> end  
> end
> 
> k = 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

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 13, 2010, 10:58pm UTC](https://www.ruby-forum.com/t/ffi-kerberos/181512/7 "2010-01-13T22:58:38Z")

</div>

Luc H. wrote:

> 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 = 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)

Thank you. This was very helpful.

Regards,

Dan
