// Copyright 2013-2015 Apcera Inc. All rights reserved. package gssapi /* #include #include #include const size_t gss_OID_size=sizeof(gss_OID_desc); void helper_gss_OID_desc_free_elements(gss_OID oid) { free(oid->elements); } void helper_gss_OID_desc_set_elements(gss_OID oid, OM_uint32 l, void *p) { oid->length = l; oid->elements = p; } void helper_gss_OID_desc_get_elements(gss_OID oid, OM_uint32 *l, char **p) { *l = oid->length; *p = oid->elements; } int wrap_gss_oid_equal(void *fp, gss_OID oid1, gss_OID oid2) { return ((int(*) (gss_OID, gss_OID)) fp)(oid1, oid2); } */ import "C" import ( "bytes" "fmt" "unsafe" ) // NewOID initializes a new OID. (Object Identifier) func (lib *Lib) NewOID() *OID { return &OID{Lib: lib} } // MakeOIDBytes makes an OID encapsulating a byte slice. Note that it does not // duplicate the data, but rather it points to it directly. func (lib *Lib) MakeOIDBytes(data []byte) (*OID, error) { oid := lib.NewOID() s := C.malloc(C.gss_OID_size) // s for struct if s == nil { return nil, ErrMallocFailed } C.memset(s, 0, C.gss_OID_size) l := C.size_t(len(data)) e := C.malloc(l) // c for contents if e == nil { return nil, ErrMallocFailed } C.memmove(e, (unsafe.Pointer)(&data[0]), l) oid.C_gss_OID = C.gss_OID(s) oid.alloc = allocMalloc // because of the alignment issues I can't access o.oid's fields from go, // so invoking a C function to do the same as: // oid.C_gss_OID.length = l // oid.C_gss_OID.elements = c C.helper_gss_OID_desc_set_elements(oid.C_gss_OID, C.OM_uint32(l), e) return oid, nil } // MakeOIDString makes an OID from a string. func (lib *Lib) MakeOIDString(data string) (*OID, error) { return lib.MakeOIDBytes([]byte(data)) } // Release safely frees the contents of an OID if it's allocated with malloc by // MakeOIDBytes. func (oid *OID) Release() error { if oid == nil || oid.C_gss_OID == nil { return nil } switch oid.alloc { case allocMalloc: // same as with get and set, use a C helper to free(oid.C_gss_OID.elements) C.helper_gss_OID_desc_free_elements(oid.C_gss_OID) C.free(unsafe.Pointer(oid.C_gss_OID)) oid.C_gss_OID = nil oid.alloc = allocNone } return nil } // Bytes displays the bytes of an OID. func (oid OID) Bytes() []byte { var l C.OM_uint32 var p *C.char C.helper_gss_OID_desc_get_elements(oid.C_gss_OID, &l, &p) return C.GoBytes(unsafe.Pointer(p), C.int(l)) } // String displays a string representation of an OID. func (oid *OID) String() string { var l C.OM_uint32 var p *C.char C.helper_gss_OID_desc_get_elements(oid.C_gss_OID, &l, &p) return fmt.Sprintf(`%x`, C.GoStringN(p, C.int(l))) } // Returns a symbolic name for a known OID, or the string. Note that this // function is intended for debugging and is not at all performant. func (oid *OID) DebugString() string { switch { case bytes.Equal(oid.Bytes(), oid.GSS_C_NT_USER_NAME.Bytes()): return "GSS_C_NT_USER_NAME" case bytes.Equal(oid.Bytes(), oid.GSS_C_NT_MACHINE_UID_NAME.Bytes()): return "GSS_C_NT_MACHINE_UID_NAME" case bytes.Equal(oid.Bytes(), oid.GSS_C_NT_STRING_UID_NAME.Bytes()): return "GSS_C_NT_STRING_UID_NAME" case bytes.Equal(oid.Bytes(), oid.GSS_C_NT_HOSTBASED_SERVICE_X.Bytes()): return "GSS_C_NT_HOSTBASED_SERVICE_X" case bytes.Equal(oid.Bytes(), oid.GSS_C_NT_HOSTBASED_SERVICE.Bytes()): return "GSS_C_NT_HOSTBASED_SERVICE" case bytes.Equal(oid.Bytes(), oid.GSS_C_NT_ANONYMOUS.Bytes()): return "GSS_C_NT_ANONYMOUS" case bytes.Equal(oid.Bytes(), oid.GSS_C_NT_EXPORT_NAME.Bytes()): return "GSS_C_NT_EXPORT_NAME" case bytes.Equal(oid.Bytes(), oid.GSS_KRB5_NT_PRINCIPAL_NAME.Bytes()): return "GSS_KRB5_NT_PRINCIPAL_NAME" case bytes.Equal(oid.Bytes(), oid.GSS_KRB5_NT_PRINCIPAL.Bytes()): return "GSS_KRB5_NT_PRINCIPAL" case bytes.Equal(oid.Bytes(), oid.GSS_MECH_KRB5.Bytes()): return "GSS_MECH_KRB5" case bytes.Equal(oid.Bytes(), oid.GSS_MECH_KRB5_LEGACY.Bytes()): return "GSS_MECH_KRB5_LEGACY" case bytes.Equal(oid.Bytes(), oid.GSS_MECH_KRB5_OLD.Bytes()): return "GSS_MECH_KRB5_OLD" case bytes.Equal(oid.Bytes(), oid.GSS_MECH_SPNEGO.Bytes()): return "GSS_MECH_SPNEGO" case bytes.Equal(oid.Bytes(), oid.GSS_MECH_IAKERB.Bytes()): return "GSS_MECH_IAKERB" case bytes.Equal(oid.Bytes(), oid.GSS_MECH_NTLMSSP.Bytes()): return "GSS_MECH_NTLMSSP" } return oid.String() }