in src/kerberosgss.c [421:511]
int authenticate_gss_client_wrap(
gss_client_state* state, const char* challenge, const char* user,
int protect
) {
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;
char buf[4096], server_conf_flags;
unsigned long buf_size;
// Always clear out the old response
if (state->response != NULL) {
free(state->response);
state->response = NULL;
}
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;
}
if (user) {
// get bufsize
server_conf_flags = ((char*) input_token.value)[0];
((char*) input_token.value)[0] = 0;
buf_size = ntohl(*((long *) input_token.value));
free(input_token.value);
#ifdef PRINTFS
printf(
"User: %s, %c%c%c\n", user,
server_conf_flags & GSS_AUTH_P_NONE ? 'N' : '-',
server_conf_flags & GSS_AUTH_P_INTEGRITY ? 'I' : '-',
server_conf_flags & GSS_AUTH_P_PRIVACY ? 'P' : '-'
);
printf("Maximum GSS token size is %ld\n", buf_size);
#endif
// agree to terms (hack!)
buf_size = htonl(buf_size); // not relevant without integrity/privacy
memcpy(buf, &buf_size, 4);
buf[0] = GSS_AUTH_P_NONE;
// server decides if principal can log in as user
strncpy(buf + 4, user, sizeof(buf) - 4);
input_token.value = buf;
input_token.length = 4 + strlen(user);
}
// Do GSSAPI wrap
maj_stat = gss_wrap(
&min_stat,
state->context,
protect,
GSS_C_QOP_DEFAULT,
&input_token,
NULL,
&output_token
);
if (maj_stat != GSS_S_COMPLETE) {
set_gss_error(maj_stat, min_stat);
ret = AUTH_GSS_ERROR;
goto end;
} else {
ret = AUTH_GSS_COMPLETE;
}
// 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);
}
end:
if (output_token.value) {
gss_release_buffer(&min_stat, &output_token);
}
return ret;
}