in src/kerberosgss.c [234:347]
int authenticate_gss_client_step(
gss_client_state* state, const char* challenge, struct gss_channel_bindings_struct* channel_bindings
) {
OM_uint32 maj_stat;
OM_uint32 min_stat;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
int ret = AUTH_GSS_CONTINUE;
// Always clear out the old response
if (state->response != NULL) {
free(state->response);
state->response = NULL;
}
// If there is a challenge (data from the server) we need to give it to GSS
if (challenge && *challenge) {
size_t len;
input_token.value = base64_decode(challenge, &len);
if (input_token.value == NULL)
{
PyErr_NoMemory();
ret = AUTH_GSS_ERROR;
goto end;
}
input_token.length = len;
}
// Do GSSAPI step
Py_BEGIN_ALLOW_THREADS
maj_stat = gss_init_sec_context(
&min_stat,
state->client_creds,
&state->context,
state->server_name,
state->mech_oid,
(OM_uint32)state->gss_flags,
0,
channel_bindings,
&input_token,
NULL,
&output_token,
NULL,
NULL
);
Py_END_ALLOW_THREADS
if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) {
set_gss_error(maj_stat, min_stat);
ret = AUTH_GSS_ERROR;
goto end;
}
ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE;
// Grab the client response to send back to the server
if (output_token.length) {
state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);
if (state->response == NULL) {
PyErr_NoMemory();
ret = AUTH_GSS_ERROR;
goto end;
}
maj_stat = gss_release_buffer(&min_stat, &output_token);
}
// Try to get the user name if we have completed all GSS operations
if (ret == AUTH_GSS_COMPLETE) {
gss_name_t gssuser = GSS_C_NO_NAME;
maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL, NULL, NULL, NULL);
if (GSS_ERROR(maj_stat)) {
set_gss_error(maj_stat, min_stat);
ret = AUTH_GSS_ERROR;
goto end;
}
gss_buffer_desc name_token;
name_token.length = 0;
maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL);
if (GSS_ERROR(maj_stat)) {
if (name_token.value) {
gss_release_buffer(&min_stat, &name_token);
}
gss_release_name(&min_stat, &gssuser);
set_gss_error(maj_stat, min_stat);
ret = AUTH_GSS_ERROR;
goto end;
} else {
if (state->username != NULL) {
free(state->username);
state->username = NULL;
}
state->username = (char *)malloc(name_token.length + 1);
if (state->username == NULL) {
PyErr_NoMemory();
ret = AUTH_GSS_ERROR;
goto end;
}
strncpy(state->username, (char*) name_token.value, name_token.length);
state->username[name_token.length] = 0;
gss_release_buffer(&min_stat, &name_token);
gss_release_name(&min_stat, &gssuser);
}
}
end:
if (output_token.value) {
gss_release_buffer(&min_stat, &output_token);
}
if (input_token.value) {
free(input_token.value);
}
return ret;
}