1*ae771770SStanislav Sedov #include "mech_locl.h"
2*ae771770SStanislav Sedov #include "heim_threads.h"
3*ae771770SStanislav Sedov
4*ae771770SStanislav Sedov struct mg_thread_ctx {
5*ae771770SStanislav Sedov gss_OID mech;
6*ae771770SStanislav Sedov OM_uint32 maj_stat;
7*ae771770SStanislav Sedov OM_uint32 min_stat;
8*ae771770SStanislav Sedov gss_buffer_desc maj_error;
9*ae771770SStanislav Sedov gss_buffer_desc min_error;
10*ae771770SStanislav Sedov };
11*ae771770SStanislav Sedov
12*ae771770SStanislav Sedov static HEIMDAL_MUTEX context_mutex = HEIMDAL_MUTEX_INITIALIZER;
13*ae771770SStanislav Sedov static int created_key;
14*ae771770SStanislav Sedov static HEIMDAL_thread_key context_key;
15*ae771770SStanislav Sedov
16*ae771770SStanislav Sedov
17*ae771770SStanislav Sedov static void
destroy_context(void * ptr)18*ae771770SStanislav Sedov destroy_context(void *ptr)
19*ae771770SStanislav Sedov {
20*ae771770SStanislav Sedov struct mg_thread_ctx *mg = ptr;
21*ae771770SStanislav Sedov OM_uint32 junk;
22*ae771770SStanislav Sedov
23*ae771770SStanislav Sedov if (mg == NULL)
24*ae771770SStanislav Sedov return;
25*ae771770SStanislav Sedov
26*ae771770SStanislav Sedov gss_release_buffer(&junk, &mg->maj_error);
27*ae771770SStanislav Sedov gss_release_buffer(&junk, &mg->min_error);
28*ae771770SStanislav Sedov free(mg);
29*ae771770SStanislav Sedov }
30*ae771770SStanislav Sedov
31*ae771770SStanislav Sedov
32*ae771770SStanislav Sedov static struct mg_thread_ctx *
_gss_mechglue_thread(void)33*ae771770SStanislav Sedov _gss_mechglue_thread(void)
34*ae771770SStanislav Sedov {
35*ae771770SStanislav Sedov struct mg_thread_ctx *ctx;
36*ae771770SStanislav Sedov int ret = 0;
37*ae771770SStanislav Sedov
38*ae771770SStanislav Sedov HEIMDAL_MUTEX_lock(&context_mutex);
39*ae771770SStanislav Sedov
40*ae771770SStanislav Sedov if (!created_key) {
41*ae771770SStanislav Sedov HEIMDAL_key_create(&context_key, destroy_context, ret);
42*ae771770SStanislav Sedov if (ret) {
43*ae771770SStanislav Sedov HEIMDAL_MUTEX_unlock(&context_mutex);
44*ae771770SStanislav Sedov return NULL;
45*ae771770SStanislav Sedov }
46*ae771770SStanislav Sedov created_key = 1;
47*ae771770SStanislav Sedov }
48*ae771770SStanislav Sedov HEIMDAL_MUTEX_unlock(&context_mutex);
49*ae771770SStanislav Sedov
50*ae771770SStanislav Sedov ctx = HEIMDAL_getspecific(context_key);
51*ae771770SStanislav Sedov if (ctx == NULL) {
52*ae771770SStanislav Sedov
53*ae771770SStanislav Sedov ctx = calloc(1, sizeof(*ctx));
54*ae771770SStanislav Sedov if (ctx == NULL)
55*ae771770SStanislav Sedov return NULL;
56*ae771770SStanislav Sedov HEIMDAL_setspecific(context_key, ctx, ret);
57*ae771770SStanislav Sedov if (ret) {
58*ae771770SStanislav Sedov free(ctx);
59*ae771770SStanislav Sedov return NULL;
60*ae771770SStanislav Sedov }
61*ae771770SStanislav Sedov }
62*ae771770SStanislav Sedov return ctx;
63*ae771770SStanislav Sedov }
64*ae771770SStanislav Sedov
65*ae771770SStanislav Sedov OM_uint32
_gss_mg_get_error(const gss_OID mech,OM_uint32 type,OM_uint32 value,gss_buffer_t string)66*ae771770SStanislav Sedov _gss_mg_get_error(const gss_OID mech, OM_uint32 type,
67*ae771770SStanislav Sedov OM_uint32 value, gss_buffer_t string)
68*ae771770SStanislav Sedov {
69*ae771770SStanislav Sedov struct mg_thread_ctx *mg;
70*ae771770SStanislav Sedov
71*ae771770SStanislav Sedov mg = _gss_mechglue_thread();
72*ae771770SStanislav Sedov if (mg == NULL)
73*ae771770SStanislav Sedov return GSS_S_BAD_STATUS;
74*ae771770SStanislav Sedov
75*ae771770SStanislav Sedov #if 0
76*ae771770SStanislav Sedov /*
77*ae771770SStanislav Sedov * We cant check the mech here since a pseudo-mech might have
78*ae771770SStanislav Sedov * called an lower layer and then the mech info is all broken
79*ae771770SStanislav Sedov */
80*ae771770SStanislav Sedov if (mech != NULL && gss_oid_equal(mg->mech, mech) == 0)
81*ae771770SStanislav Sedov return GSS_S_BAD_STATUS;
82*ae771770SStanislav Sedov #endif
83*ae771770SStanislav Sedov
84*ae771770SStanislav Sedov switch (type) {
85*ae771770SStanislav Sedov case GSS_C_GSS_CODE: {
86*ae771770SStanislav Sedov if (value != mg->maj_stat || mg->maj_error.length == 0)
87*ae771770SStanislav Sedov break;
88*ae771770SStanislav Sedov string->value = malloc(mg->maj_error.length + 1);
89*ae771770SStanislav Sedov string->length = mg->maj_error.length;
90*ae771770SStanislav Sedov memcpy(string->value, mg->maj_error.value, mg->maj_error.length);
91*ae771770SStanislav Sedov ((char *) string->value)[string->length] = '\0';
92*ae771770SStanislav Sedov return GSS_S_COMPLETE;
93*ae771770SStanislav Sedov }
94*ae771770SStanislav Sedov case GSS_C_MECH_CODE: {
95*ae771770SStanislav Sedov if (value != mg->min_stat || mg->min_error.length == 0)
96*ae771770SStanislav Sedov break;
97*ae771770SStanislav Sedov string->value = malloc(mg->min_error.length + 1);
98*ae771770SStanislav Sedov string->length = mg->min_error.length;
99*ae771770SStanislav Sedov memcpy(string->value, mg->min_error.value, mg->min_error.length);
100*ae771770SStanislav Sedov ((char *) string->value)[string->length] = '\0';
101*ae771770SStanislav Sedov return GSS_S_COMPLETE;
102*ae771770SStanislav Sedov }
103*ae771770SStanislav Sedov }
104*ae771770SStanislav Sedov string->value = NULL;
105*ae771770SStanislav Sedov string->length = 0;
106*ae771770SStanislav Sedov return GSS_S_BAD_STATUS;
107*ae771770SStanislav Sedov }
108*ae771770SStanislav Sedov
109*ae771770SStanislav Sedov void
_gss_mg_error(gssapi_mech_interface m,OM_uint32 maj,OM_uint32 min)110*ae771770SStanislav Sedov _gss_mg_error(gssapi_mech_interface m, OM_uint32 maj, OM_uint32 min)
111*ae771770SStanislav Sedov {
112*ae771770SStanislav Sedov OM_uint32 major_status, minor_status;
113*ae771770SStanislav Sedov OM_uint32 message_content;
114*ae771770SStanislav Sedov struct mg_thread_ctx *mg;
115*ae771770SStanislav Sedov
116*ae771770SStanislav Sedov /*
117*ae771770SStanislav Sedov * Mechs without gss_display_status() does
118*ae771770SStanislav Sedov * gss_mg_collect_error() by themself.
119*ae771770SStanislav Sedov */
120*ae771770SStanislav Sedov if (m->gm_display_status == NULL)
121*ae771770SStanislav Sedov return ;
122*ae771770SStanislav Sedov
123*ae771770SStanislav Sedov mg = _gss_mechglue_thread();
124*ae771770SStanislav Sedov if (mg == NULL)
125*ae771770SStanislav Sedov return;
126*ae771770SStanislav Sedov
127*ae771770SStanislav Sedov gss_release_buffer(&minor_status, &mg->maj_error);
128*ae771770SStanislav Sedov gss_release_buffer(&minor_status, &mg->min_error);
129*ae771770SStanislav Sedov
130*ae771770SStanislav Sedov mg->mech = &m->gm_mech_oid;
131*ae771770SStanislav Sedov mg->maj_stat = maj;
132*ae771770SStanislav Sedov mg->min_stat = min;
133*ae771770SStanislav Sedov
134*ae771770SStanislav Sedov major_status = m->gm_display_status(&minor_status,
135*ae771770SStanislav Sedov maj,
136*ae771770SStanislav Sedov GSS_C_GSS_CODE,
137*ae771770SStanislav Sedov &m->gm_mech_oid,
138*ae771770SStanislav Sedov &message_content,
139*ae771770SStanislav Sedov &mg->maj_error);
140*ae771770SStanislav Sedov if (GSS_ERROR(major_status)) {
141*ae771770SStanislav Sedov mg->maj_error.value = NULL;
142*ae771770SStanislav Sedov mg->maj_error.length = 0;
143*ae771770SStanislav Sedov }
144*ae771770SStanislav Sedov major_status = m->gm_display_status(&minor_status,
145*ae771770SStanislav Sedov min,
146*ae771770SStanislav Sedov GSS_C_MECH_CODE,
147*ae771770SStanislav Sedov &m->gm_mech_oid,
148*ae771770SStanislav Sedov &message_content,
149*ae771770SStanislav Sedov &mg->min_error);
150*ae771770SStanislav Sedov if (GSS_ERROR(major_status)) {
151*ae771770SStanislav Sedov mg->min_error.value = NULL;
152*ae771770SStanislav Sedov mg->min_error.length = 0;
153*ae771770SStanislav Sedov }
154*ae771770SStanislav Sedov }
155*ae771770SStanislav Sedov
156*ae771770SStanislav Sedov void
gss_mg_collect_error(gss_OID mech,OM_uint32 maj,OM_uint32 min)157*ae771770SStanislav Sedov gss_mg_collect_error(gss_OID mech, OM_uint32 maj, OM_uint32 min)
158*ae771770SStanislav Sedov {
159*ae771770SStanislav Sedov gssapi_mech_interface m = __gss_get_mechanism(mech);
160*ae771770SStanislav Sedov if (m == NULL)
161*ae771770SStanislav Sedov return;
162*ae771770SStanislav Sedov _gss_mg_error(m, maj, min);
163*ae771770SStanislav Sedov }
164