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