int authenticate_gss_client_wrap()

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;
}