blob: 0ca591f83fdd164c29404804dfb7ff4038bd7371 [file] [log] [blame]
Don Newton379ae252019-04-01 12:17:06 -04001//+build gssapi
2//+build linux darwin
3
4#include <string.h>
5#include <stdio.h>
6#include "gss_wrapper.h"
7
8OM_uint32 gssapi_canonicalize_name(
9 OM_uint32* minor_status,
10 char *input_name,
11 gss_OID input_name_type,
12 gss_name_t *output_name
13)
14{
15 OM_uint32 major_status;
16 gss_name_t imported_name = GSS_C_NO_NAME;
17 gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
18
19 buffer.value = input_name;
20 buffer.length = strlen(input_name);
21 major_status = gss_import_name(minor_status, &buffer, input_name_type, &imported_name);
22 if (GSS_ERROR(major_status)) {
23 return major_status;
24 }
25
26 major_status = gss_canonicalize_name(minor_status, imported_name, (gss_OID)gss_mech_krb5, output_name);
27 if (imported_name != GSS_C_NO_NAME) {
28 OM_uint32 ignored;
29 gss_release_name(&ignored, &imported_name);
30 }
31
32 return major_status;
33}
34
35int gssapi_error_desc(
36 OM_uint32 maj_stat,
37 OM_uint32 min_stat,
38 char **desc
39)
40{
41 OM_uint32 stat = maj_stat;
42 int stat_type = GSS_C_GSS_CODE;
43 if (min_stat != 0) {
44 stat = min_stat;
45 stat_type = GSS_C_MECH_CODE;
46 }
47
48 OM_uint32 local_maj_stat, local_min_stat;
49 OM_uint32 msg_ctx = 0;
50 gss_buffer_desc desc_buffer;
51 do
52 {
53 local_maj_stat = gss_display_status(
54 &local_min_stat,
55 stat,
56 stat_type,
57 GSS_C_NO_OID,
58 &msg_ctx,
59 &desc_buffer
60 );
61 if (GSS_ERROR(local_maj_stat)) {
62 return GSSAPI_ERROR;
63 }
64
65 if (*desc) {
66 free(*desc);
67 }
68
69 *desc = malloc(desc_buffer.length+1);
70 memcpy(*desc, desc_buffer.value, desc_buffer.length+1);
71
72 gss_release_buffer(&local_min_stat, &desc_buffer);
73 }
74 while(msg_ctx != 0);
75
76 return GSSAPI_OK;
77}
78
79int gssapi_client_init(
80 gssapi_client_state *client,
81 char* spn,
82 char* username,
83 char* password
84)
85{
86 client->cred = GSS_C_NO_CREDENTIAL;
87 client->ctx = GSS_C_NO_CONTEXT;
88
89 client->maj_stat = gssapi_canonicalize_name(&client->min_stat, spn, GSS_C_NT_HOSTBASED_SERVICE, &client->spn);
90 if (GSS_ERROR(client->maj_stat)) {
91 return GSSAPI_ERROR;
92 }
93
94 if (username) {
95 gss_name_t name;
96 client->maj_stat = gssapi_canonicalize_name(&client->min_stat, username, GSS_C_NT_USER_NAME, &name);
97 if (GSS_ERROR(client->maj_stat)) {
98 return GSSAPI_ERROR;
99 }
100
101 if (password) {
102 gss_buffer_desc password_buffer;
103 password_buffer.value = password;
104 password_buffer.length = strlen(password);
105 client->maj_stat = gss_acquire_cred_with_password(&client->min_stat, name, &password_buffer, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client->cred, NULL, NULL);
106 } else {
107 client->maj_stat = gss_acquire_cred(&client->min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client->cred, NULL, NULL);
108 }
109
110 if (GSS_ERROR(client->maj_stat)) {
111 return GSSAPI_ERROR;
112 }
113
114 OM_uint32 ignored;
115 gss_release_name(&ignored, &name);
116 }
117
118 return GSSAPI_OK;
119}
120
121int gssapi_client_username(
122 gssapi_client_state *client,
123 char** username
124)
125{
126 OM_uint32 ignored;
127 gss_name_t name = GSS_C_NO_NAME;
128
129 client->maj_stat = gss_inquire_context(&client->min_stat, client->ctx, &name, NULL, NULL, NULL, NULL, NULL, NULL);
130 if (GSS_ERROR(client->maj_stat)) {
131 return GSSAPI_ERROR;
132 }
133
134 gss_buffer_desc name_buffer;
135 client->maj_stat = gss_display_name(&client->min_stat, name, &name_buffer, NULL);
136 if (GSS_ERROR(client->maj_stat)) {
137 gss_release_name(&ignored, &name);
138 return GSSAPI_ERROR;
139 }
140
141 *username = malloc(name_buffer.length+1);
142 memcpy(*username, name_buffer.value, name_buffer.length+1);
143
144 gss_release_buffer(&ignored, &name_buffer);
145 gss_release_name(&ignored, &name);
146 return GSSAPI_OK;
147}
148
149int gssapi_client_negotiate(
150 gssapi_client_state *client,
151 void* input,
152 size_t input_length,
153 void** output,
154 size_t* output_length
155)
156{
157 gss_buffer_desc input_buffer = GSS_C_EMPTY_BUFFER;
158 gss_buffer_desc output_buffer = GSS_C_EMPTY_BUFFER;
159
160 if (input) {
161 input_buffer.value = input;
162 input_buffer.length = input_length;
163 }
164
165 client->maj_stat = gss_init_sec_context(
166 &client->min_stat,
167 client->cred,
168 &client->ctx,
169 client->spn,
170 GSS_C_NO_OID,
171 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
172 0,
173 GSS_C_NO_CHANNEL_BINDINGS,
174 &input_buffer,
175 NULL,
176 &output_buffer,
177 NULL,
178 NULL
179 );
180
181 if (output_buffer.length) {
182 *output = malloc(output_buffer.length);
183 *output_length = output_buffer.length;
184 memcpy(*output, output_buffer.value, output_buffer.length);
185
186 OM_uint32 ignored;
187 gss_release_buffer(&ignored, &output_buffer);
188 }
189
190 if (GSS_ERROR(client->maj_stat)) {
191 return GSSAPI_ERROR;
192 } else if (client->maj_stat == GSS_S_CONTINUE_NEEDED) {
193 return GSSAPI_CONTINUE;
194 }
195
196 return GSSAPI_OK;
197}
198
199int gssapi_client_wrap_msg(
200 gssapi_client_state *client,
201 void* input,
202 size_t input_length,
203 void** output,
204 size_t* output_length
205)
206{
207 gss_buffer_desc input_buffer = GSS_C_EMPTY_BUFFER;
208 gss_buffer_desc output_buffer = GSS_C_EMPTY_BUFFER;
209
210 input_buffer.value = input;
211 input_buffer.length = input_length;
212
213 client->maj_stat = gss_wrap(&client->min_stat, client->ctx, 0, GSS_C_QOP_DEFAULT, &input_buffer, NULL, &output_buffer);
214
215 if (output_buffer.length) {
216 *output = malloc(output_buffer.length);
217 *output_length = output_buffer.length;
218 memcpy(*output, output_buffer.value, output_buffer.length);
219
220 gss_release_buffer(&client->min_stat, &output_buffer);
221 }
222
223 if (GSS_ERROR(client->maj_stat)) {
224 return GSSAPI_ERROR;
225 }
226
227 return GSSAPI_OK;
228}
229
230int gssapi_client_destroy(
231 gssapi_client_state *client
232)
233{
234 OM_uint32 ignored;
235 if (client->ctx != GSS_C_NO_CONTEXT) {
236 gss_delete_sec_context(&ignored, &client->ctx, GSS_C_NO_BUFFER);
237 }
238
239 if (client->spn != GSS_C_NO_NAME) {
240 gss_release_name(&ignored, &client->spn);
241 }
242
243 if (client->cred != GSS_C_NO_CREDENTIAL) {
244 gss_release_cred(&ignored, &client->cred);
245 }
246
247 return GSSAPI_OK;
248}