2
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
16
* DRI: Cyrus Daboo, cdaboo@apple.com
20
#include "kerberosgss.h"
28
static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min);
30
extern PyObject *GssException_class;
31
extern PyObject *KrbException_class;
33
int authenticate_gss_client_init(const char* service, gss_client_state *state)
37
gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;
38
int ret = AUTH_GSS_COMPLETE;
40
state->server_name = GSS_C_NO_NAME;
41
state->context = GSS_C_NO_CONTEXT;
42
state->username = NULL;
43
state->response = NULL;
45
// Import server name first
46
name_token.length = strlen(service);
47
name_token.value = (char *)service;
49
maj_stat = gss_import_name(&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name);
51
if (GSS_ERROR(maj_stat))
53
set_gss_error(maj_stat, min_stat);
62
int authenticate_gss_client_clean(gss_client_state *state)
66
int ret = AUTH_GSS_COMPLETE;
68
if (state->context != GSS_C_NO_CONTEXT)
69
maj_stat = gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER);
70
if (state->server_name != GSS_C_NO_NAME)
71
maj_stat = gss_release_name(&min_stat, &state->server_name);
72
if (state->username != NULL)
74
free(state->username);
75
state->username = NULL;
77
if (state->response != NULL)
79
free(state->response);
80
state->response = NULL;
86
int authenticate_gss_client_step(gss_client_state *state, const char* challenge)
90
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
91
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
92
int ret = AUTH_GSS_CONTINUE;
94
// Always clear out the old response
95
if (state->response != NULL)
97
free(state->response);
98
state->response = NULL;
101
// If there is a challenge (data from the server) we need to give it to GSS
102
if (challenge && *challenge)
105
input_token.value = base64_decode(challenge, &len);
106
input_token.length = len;
110
maj_stat = gss_init_sec_context(&min_stat,
115
GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
117
GSS_C_NO_CHANNEL_BINDINGS,
124
if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED))
126
set_gss_error(maj_stat, min_stat);
127
ret = AUTH_GSS_ERROR;
131
ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE;
132
// Grab the client response to send back to the server
133
if (output_token.length)
135
state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);;
136
maj_stat = gss_release_buffer(&min_stat, &output_token);
139
// Try to get the user name if we have completed all GSS operations
140
if (ret == AUTH_GSS_COMPLETE)
142
gss_name_t gssuser = GSS_C_NO_NAME;
143
maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL, NULL, NULL, NULL);
144
if (GSS_ERROR(maj_stat))
146
set_gss_error(maj_stat, min_stat);
147
ret = AUTH_GSS_ERROR;
151
gss_buffer_desc name_token;
152
name_token.length = 0;
153
maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL);
154
if (GSS_ERROR(maj_stat))
156
if (name_token.value)
157
gss_release_buffer(&min_stat, &name_token);
158
gss_release_name(&min_stat, &gssuser);
160
set_gss_error(maj_stat, min_stat);
161
ret = AUTH_GSS_ERROR;
166
state->username = (char *)malloc(name_token.length + 1);
167
strncpy(state->username, (char*) name_token.value, name_token.length);
168
state->username[name_token.length] = 0;
169
gss_release_buffer(&min_stat, &name_token);
170
gss_release_name(&min_stat, &gssuser);
174
if (output_token.value)
175
gss_release_buffer(&min_stat, &output_token);
176
if (input_token.value)
177
free(input_token.value);
181
int authenticate_gss_server_init(const char* service, gss_server_state *state)
185
gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;
186
int ret = AUTH_GSS_COMPLETE;
188
state->context = GSS_C_NO_CONTEXT;
189
state->server_name = GSS_C_NO_NAME;
190
state->client_name = GSS_C_NO_NAME;
191
state->server_creds = GSS_C_NO_CREDENTIAL;
192
state->client_creds = GSS_C_NO_CREDENTIAL;
193
state->username = NULL;
194
state->response = NULL;
196
// Import server name first
197
name_token.length = strlen(service);
198
name_token.value = (char *)service;
200
maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &state->server_name);
202
if (GSS_ERROR(maj_stat))
204
set_gss_error(maj_stat, min_stat);
205
ret = AUTH_GSS_ERROR;
210
maj_stat = gss_acquire_cred(&min_stat, state->server_name, GSS_C_INDEFINITE,
211
GSS_C_NO_OID_SET, GSS_C_ACCEPT, &state->server_creds, NULL, NULL);
213
if (GSS_ERROR(maj_stat))
215
set_gss_error(maj_stat, min_stat);
216
ret = AUTH_GSS_ERROR;
224
int authenticate_gss_server_clean(gss_server_state *state)
228
int ret = AUTH_GSS_COMPLETE;
230
if (state->context != GSS_C_NO_CONTEXT)
231
maj_stat = gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER);
232
if (state->server_name != GSS_C_NO_NAME)
233
maj_stat = gss_release_name(&min_stat, &state->server_name);
234
if (state->client_name != GSS_C_NO_NAME)
235
maj_stat = gss_release_name(&min_stat, &state->client_name);
236
if (state->server_creds != GSS_C_NO_CREDENTIAL)
237
maj_stat = gss_release_cred(&min_stat, &state->server_creds);
238
if (state->client_creds != GSS_C_NO_CREDENTIAL)
239
maj_stat = gss_release_cred(&min_stat, &state->client_creds);
240
if (state->username != NULL)
242
free(state->username);
243
state->username = NULL;
245
if (state->response != NULL)
247
free(state->response);
248
state->response = NULL;
254
int authenticate_gss_server_step(gss_server_state *state, const char *challenge)
258
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
259
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
260
int ret = AUTH_GSS_CONTINUE;
262
// Always clear out the old response
263
if (state->response != NULL)
265
free(state->response);
266
state->response = NULL;
269
// If there is a challenge (data from the server) we need to give it to GSS
270
if (challenge && *challenge)
273
input_token.value = base64_decode(challenge, &len);
274
input_token.length = len;
278
PyErr_SetString(KrbException_class, "No challenge parameter in request from client");
279
ret = AUTH_GSS_ERROR;
283
maj_stat = gss_accept_sec_context(&min_stat,
287
GSS_C_NO_CHANNEL_BINDINGS,
293
&state->client_creds);
295
if (GSS_ERROR(maj_stat))
297
set_gss_error(maj_stat, min_stat);
298
ret = AUTH_GSS_ERROR;
302
// Grab the server response to send back to the client
303
if (output_token.length)
305
state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);;
306
maj_stat = gss_release_buffer(&min_stat, &output_token);
309
maj_stat = gss_display_name(&min_stat, state->client_name, &output_token, NULL);
310
if (GSS_ERROR(maj_stat))
312
set_gss_error(maj_stat, min_stat);
313
ret = AUTH_GSS_ERROR;
316
state->username = (char *)malloc(output_token.length + 1);
317
strncpy(state->username, (char*) output_token.value, output_token.length);
318
state->username[output_token.length] = 0;
320
ret = AUTH_GSS_COMPLETE;
323
if (output_token.length)
324
gss_release_buffer(&min_stat, &output_token);
325
if (input_token.value)
326
free(input_token.value);
331
static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min)
333
OM_uint32 maj_stat, min_stat;
334
OM_uint32 msg_ctx = 0;
335
gss_buffer_desc status_string;
341
maj_stat = gss_display_status (&min_stat,
347
if (GSS_ERROR(maj_stat))
349
strncpy(buf_maj, (char*) status_string.value, sizeof(buf_maj));
350
gss_release_buffer(&min_stat, &status_string);
352
maj_stat = gss_display_status (&min_stat,
358
if (!GSS_ERROR(maj_stat))
360
strncpy(buf_min, (char*) status_string.value, sizeof(buf_min));
361
gss_release_buffer(&min_stat, &status_string);
363
} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
365
PyErr_SetObject(GssException_class, Py_BuildValue("((s:i)(s:i))", buf_maj, err_maj, buf_min, err_min));