1 /*
2 * Copyright 1999-2006 University of Chicago
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 #include "globus_common.h"
18 #include "globus_xio_buffer.h"
19 #include "globus_xio_tcp_driver.h"
20 #include "globus_xio_http.h"
21 #include "globus_xio_gsi.h"
22 #include "globus_xsd_types.h"
23 #include "globus_soap_message_handle.h"
24 #include "globus_i_soap_message.h"
25 #include "globus_soap_message.h"
26 #include "globus_soap_message_attrs.h"
27 #include "globus_error_gssapi.h"
28
29 /**
30 * @defgroup globus_soap_message_transport SOAP Transport
31 *
32 * Functions used to read, write, open, and close XIO handles used internally
33 * by the SOAP engine.
34 */
35 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
36 typedef struct
37 {
38 struct globus_soap_message_handle_s * message;
39 int no_response;
40 globus_soap_message_callback_func_t callback;
41 void * args;
42 enum
43 {
44 GLOBUS_SOAP_MESSAGE_REQUEST_CALLBACK,
45 GLOBUS_SOAP_MESSAGE_RESPONSE_CALLBACK
46 } type;
47 } globus_l_soap_message_callback_handle_t;
48
49 typedef struct
50 {
51 globus_soap_message_callback_func_t callback;
52 void * args;
53 } globus_l_soap_message_close_callback_t;
54
55 globus_result_t
56 globus_i_soap_message_setup_unbuffered_writer(
57 globus_soap_message_handle_t message);
58
59 globus_result_t
60 globus_i_soap_message_reset_reader(
61 globus_soap_message_handle_t handle);
62
63 globus_result_t
64 globus_i_soap_message_setup_transport_security(
65 globus_soap_message_attr_t attrs,
66 globus_xio_attr_t xio_attr);
67
68 static
69 int
70 globus_l_soap_message_handle_libxml_io_read_callback(
71 void * context,
72 char * buffer,
73 int length);
74
75 static
76 int
77 globus_l_soap_message_handle_libxml_io_write_callback(
78 void * context,
79 const char * buffer,
80 int length);
81
82 static
83 int
84 globus_l_soap_message_handle_libxml_io_close_callback(
85 void * context);
86
87 static
88 void
89 globus_l_soap_message_open_callback(
90 globus_xio_handle_t handle,
91 globus_result_t result,
92 void * user_args);
93
94 static
95 void
96 globus_l_soap_message_flush_callback(
97 globus_xio_handle_t handle,
98 globus_result_t result,
99 globus_byte_t * buffer,
100 globus_size_t len,
101 globus_size_t nbytes,
102 globus_xio_data_descriptor_t data_desc,
103 void * user_args);
104
105 static
106 void
107 globus_l_soap_message_read_callback(
108 globus_xio_handle_t handle,
109 globus_result_t result,
110 globus_byte_t * buffer,
111 globus_size_t len,
112 globus_size_t nbytes,
113 globus_xio_data_descriptor_t data_desc,
114 void * user_arg);
115
116 static
117 void
118 globus_l_soap_message_response_callback(
119 void * args);
120
121 static
122 void
123 globus_l_soap_message_response_ready_callback(
124 globus_xio_handle_t handle,
125 globus_result_t result,
126 globus_byte_t * buffer,
127 globus_size_t len,
128 globus_size_t nbytes,
129 globus_xio_data_descriptor_t data_desc,
130 void * user_arg);
131
132 static
133 globus_bool_t
134 globus_l_soap_message_timeout_callback(
135 globus_xio_handle_t handle,
136 globus_xio_operation_type_t type,
137 void * user_arg);
138
139 static
140 void
141 globus_l_soap_message_register_close_callback(
142 globus_xio_handle_t handle,
143 globus_result_t result,
144 void * args);
145
146 static
147 globus_result_t
148 globus_l_authz_host_self(
149 globus_soap_message_handle_t message,
150 globus_soap_message_auth_method_t authn);
151
152 static
153 globus_result_t
154 globus_l_create_name_from_url(
155 const char * url_string,
156 gss_name_t * name);
157 #endif
158
159 /**
160 * Reset the I/O handle associate with a SOAP handle to prepare for writing
161 * @ingroup globus_soap_message_transport
162 * Used by the SOAP processor to prepare for writing a SOAP request or
163 * response. Clears the buffers used by the transport layer and sets the
164 * buffering driver to be ready for handling writes.
165 *
166 * @param message
167 * SOAP message handle to prepare.
168 *
169 * @retval GLOBUS_SUCCESS
170 * SOAP message handle setup successfully.
171 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
172 * The @a message parameter is NULL.
173 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT
174 * Unable to set up the handle to write.
175 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_INIT_FAILED
176 * Unable to set up the handle to write.
177 */
178 globus_result_t
179 globus_soap_message_setup_writer(
180 globus_soap_message_handle_t message)
181 21554 {
182 21554 xmlOutputBufferPtr output_buffer = NULL;
183 21554 globus_result_t result = GLOBUS_SUCCESS;
184 GlobusFuncName(globus_soap_message_setup_writer);
185 21554 GlobusSoapMessageDebugEnter();
186
187 21554 if (message == NULL)
188 {
189 0 result = GlobusSoapMessageErrorNullParam;
190
191 0 goto exit;
192 }
193
194 21554 result = globus_xio_handle_cntl(
195 message->xio_handle,
196 globus_i_soap_message_buffer_driver,
197 GLOBUS_XIO_BUFFER_CLEAR);
198 21554 if(result != GLOBUS_SUCCESS)
199 {
200 0 result = GlobusSoapMessageErrorFailedTransport(
201 result, "Failed to enable buffering for message write");
202 0 goto exit;
203 }
204
205 21554 result = globus_xio_handle_cntl(
206 message->xio_handle,
207 globus_i_soap_message_buffer_driver,
208 GLOBUS_XIO_BUFFER_ENABLE_WRITE_BUFFERING);
209 21554 if(result != GLOBUS_SUCCESS)
210 {
211 0 result = GlobusSoapMessageErrorFailedTransport(
212 result, "Failed to enable buffering for message write");
213 0 goto exit;
214 }
215
216 21554 output_buffer = xmlOutputBufferCreateIO(
217 globus_l_soap_message_handle_libxml_io_write_callback,
218 globus_l_soap_message_handle_libxml_io_close_callback,
219 message,
220 0);
221 21554 if(!output_buffer)
222 {
223 0 result = GlobusSoapMessageErrorInitFailed(
224 "Failed to initialize output buffer");
225 0 goto exit;
226 }
227
228 21554 message->writer = xmlNewTextWriter(output_buffer);
229 21554 if(!message->writer)
230 {
231 0 result = GlobusSoapMessageErrorInitFailed(
232 "Failed to initialize xmlWriter");
233 0 goto free_output;
234 }
235
236 21554 goto exit;
237
238 0 free_output:
239
240 0 xmlOutputBufferClose(output_buffer);
241
242 21554 exit:
243
244 21554 GlobusSoapMessageDebugExit();
245 21554 return result;
246 }
247 /* globus_soap_message_setup_writer() */
248
249 /**
250 * Open a connect to a SOAP service
251 * @ingroup globus_soap_message_transport
252 * Connect to the service hosted at @a endpoint so that a SOAP request
253 * message can be sent to it. When the connection is established, the
254 * function pointed to by @a callback will be called.
255 *
256 * @param handle
257 * SOAP message handle to open the connection on .
258 * @param endpoint
259 * Endpoint describing where the service is located.
260 * @param callback
261 * Pointer to function to call after the open has completed.
262 * @param args
263 * Parameter to the @a callback function.
264 *
265 * @retval GLOBUS_SUCCESS
266 * Handle open begun successfully.
267 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
268 * One of @a handle, @a endpoint, or @a callback is NULL.
269 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
270 * Insufficient memory to open the SOAP connection.
271 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT
272 * SOAP message handle already opened or error opening the handle.
273 */
274 globus_result_t
275 globus_soap_message_register_open(
276 globus_soap_message_handle_t handle,
277 char * endpoint,
278 globus_soap_message_callback_func_t callback,
279 void * args)
280 11559 {
281 globus_soap_message_auth_method_t sectype;
282 11559 globus_xio_attr_t attr = NULL;
283 globus_l_soap_message_callback_handle_t * callback_handle;
284 11559 globus_result_t result = GLOBUS_SUCCESS;
285 char * soap_action;
286 11559 char * http_version = NULL;
287 11559 char * connection = NULL;
288 11559 void * timeout = NULL;
289 11559 char * quoted_soap_action = NULL;
290 GlobusFuncName(globus_soap_message_register_open);
291 11559 GlobusSoapMessageDebugEnter();
292
293 11559 if (handle == NULL || endpoint == NULL || callback == NULL)
294 {
295 0 result = GlobusSoapMessageErrorNullParam;
296
297 0 goto exit;
298 }
299 11559 globus_mutex_lock(&handle->cancel_mutex);
300 11559 handle->cancelled = 0;
301 11559 globus_mutex_unlock(&handle->cancel_mutex);
302
303 11559 callback_handle = calloc(1,
304 sizeof(globus_l_soap_message_callback_handle_t));
305 11559 if(!callback_handle)
306 {
307 0 result = GlobusSoapMessageErrorOutOfMemory;
308 0 goto exit;
309 }
310
311 11559 if(handle->xio_handle)
312 {
313 0 result = GlobusSoapMessageErrorFailedTransport(
314 result, "Session already opened");
315 0 goto exit;
316 }
317
318 11559 callback_handle->callback = callback;
319 11559 callback_handle->args = args;
320 11559 callback_handle->message = handle;
321
322 11559 result = globus_soap_message_handle_set_attr(
323 handle,
324 GLOBUS_SOAP_MESSAGE_SERVICE_ENDPOINT_KEY,
325 globus_soap_message_attr_copy_string,
326 free,
327 (void *) endpoint);
328 11559 if (result != GLOBUS_SUCCESS)
329 {
330 0 goto exit;
331 }
332
333 11559 if(strncmp(endpoint, "https://", 8) == 0)
334 {
335 5048 result = globus_xio_handle_create(
336 &handle->xio_handle,
337 globus_i_soap_message_xio_https_stack);
338 5048 if(result != GLOBUS_SUCCESS)
339 {
340 0 result = GlobusSoapMessageErrorFailedTransport(
341 result, "Failed to create xio handle with https stack");
342 0 goto exit;
343 }
344
345 5048 result = globus_xio_attr_init(&attr);
346 5048 if(result != GLOBUS_SUCCESS)
347 {
348 0 result = GlobusSoapMessageErrorFailedTransport(
349 result, "Failed to initialize xio attr");
350 0 goto exit;
351 }
352
353 5048 result = globus_i_soap_message_setup_transport_security(
354 handle->attrs,
355 attr);
356 5048 if(result != GLOBUS_SUCCESS)
357 {
358 0 result = GlobusSoapMessageErrorFailedTransport(
359 result, "Failed to initialize xio attributes for https");
360 0 goto exit;
361 }
362 }
363 else
364 {
365 6511 sectype = (globus_soap_message_auth_method_t)
366 globus_soap_message_handle_get_attr(
367 handle,
368 GLOBUS_SOAP_MESSAGE_AUTHENTICATION_METHOD_KEY);
369
370 6511 if(sectype && (sectype == GLOBUS_SOAP_MESSAGE_AUTH_SECURE))
371 {
372 /* XXX may not be a good idea if users can 'set attrs' on this
373 * handle while it is open
374 */
375 0 globus_soap_message_handle_set_attr(
376 handle,
377 GLOBUS_SOAP_MESSAGE_AUTHENTICATION_METHOD_KEY,
378 NULL,
379 NULL,
380 (void *) GLOBUS_SOAP_MESSAGE_AUTH_SECURE_MESSAGE);
381 }
382
383 6511 result = globus_xio_handle_create(&handle->xio_handle,
384 globus_i_soap_message_xio_stack);
385
386 6511 result = globus_xio_attr_init(&attr);
387 6511 if(result != GLOBUS_SUCCESS)
388 {
389 0 result = GlobusSoapMessageErrorFailedTransport(
390 result, "Failed to initialize xio attr");
391 0 goto exit;
392 }
393 }
394
395 11559 timeout = globus_soap_message_handle_get_attr(
396 handle, GLOBUS_SOAP_MESSAGE_TIMEOUT_KEY);
397 11559 if(timeout)
398 {
399 0 result = globus_xio_attr_cntl(
400 attr,
401 GLOBUS_NULL,
402 GLOBUS_XIO_ATTR_SET_TIMEOUT_ALL,
403 globus_l_soap_message_timeout_callback,
404 timeout,
405 GLOBUS_NULL);
406 0 if(result != GLOBUS_SUCCESS)
407 {
408 0 result = GlobusSoapMessageErrorFailedTransport(
409 result, "Failed to set timeout for xio handle");
410 0 goto exit;
411 }
412 }
413
414 11559 http_version = globus_soap_message_handle_get_attr(
415 handle, GLOBUS_SOAP_MESSAGE_HTTP_VERSION_KEY);
416 11559 if(http_version && !strcmp(http_version, "1.0"))
417 {
418 0 result = globus_xio_attr_cntl(
419 attr,
420 globus_i_soap_message_http_driver,
421 GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HTTP_VERSION,
422 GLOBUS_XIO_HTTP_VERSION_1_0);
423 0 if(result != GLOBUS_SUCCESS)
424 {
425 0 result = GlobusSoapMessageErrorFailedTransport(
426 result, "Failed to set HTTP version to 1.0");
427 0 goto exit;
428 }
429
430 0 result = globus_xio_attr_cntl(
431 attr,
432 globus_i_soap_message_http_driver,
433 GLOBUS_XIO_HTTP_ATTR_DELAY_WRITE_HEADER);
434 0 if(result != GLOBUS_SUCCESS)
435 {
436 0 result = GlobusSoapMessageErrorFailedTransport(
437 result, "Failed to set delay write of HTTP Header");
438 0 goto exit;
439 }
440 }
441
442 11559 result = globus_xio_attr_cntl(
443 attr, globus_i_soap_message_http_driver,
444 GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER,
445 "Content-Type",
446 "text/xml; charset=utf-8");
447 11559 if(result != GLOBUS_SUCCESS)
448 {
449 0 result = GlobusSoapMessageErrorFailedTransport(
450 result, "Failed to set HTTP request header: Content-Type");
451 0 goto exit;
452 }
453
454 11559 result = globus_xio_attr_cntl(
455 attr, globus_i_soap_message_http_driver,
456 GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER,
457 "Accept",
458 "text/xml");
459 11559 if(result != GLOBUS_SUCCESS)
460 {
461 0 result = GlobusSoapMessageErrorFailedTransport(
462 result, "Failed to set HTTP request header: Accept");
463 0 goto exit;
464 }
465
466 11559 connection = (char *) globus_soap_message_handle_get_attr(
467 handle,
468 GLOBUS_SOAP_MESSAGE_CONNECTION_KEY);
469 11559 if (connection && !strcmp(connection, "close"))
470 {
471 6613 result = globus_xio_attr_cntl(
472 attr, globus_i_soap_message_http_driver,
473 GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER,
474 "Connection",
475 "close");
476 6613 if(result != GLOBUS_SUCCESS)
477 {
478 0 result = GlobusSoapMessageErrorFailedTransport(
479 result, "Failed to set HTTP request header: Connection");
480 0 goto exit;
481 }
482 }
483
484 11559 soap_action = globus_soap_message_handle_get_attr(
485 handle, GLOBUS_SOAP_MESSAGE_SOAP_ACTION_KEY);
486 11559 if(!soap_action)
487 {
488 0 result = GlobusSoapMessageErrorFailedTransport(
489 result, "SOAPAction not set in message attributes");
490 0 goto exit;
491 }
492
493 11559 if (soap_action[0] != '"')
494 {
495 /* WS-I BP requires that SOAPAction be quoted */
496 size_t soap_action_len;
497
498 11559 soap_action_len = strlen(soap_action);
499
500 11559 quoted_soap_action = malloc(soap_action_len + 3);
501
502 11559 memcpy(quoted_soap_action + 1, soap_action, soap_action_len);
503 11559 quoted_soap_action[0] = '"';
504 11559 quoted_soap_action[soap_action_len+1] = '"';
505 11559 quoted_soap_action[soap_action_len+2] = '\0';
506
507 11559 soap_action = quoted_soap_action;
508 }
509
510 11559 result = globus_xio_attr_cntl(
511 attr,
512 globus_i_soap_message_http_driver,
513 GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER,
514 "SOAPAction",
515 soap_action);
516 11559 if(result != GLOBUS_SUCCESS)
517 {
518 0 result = GlobusSoapMessageErrorFailedTransport(
519 result, "Failed to set request method in http driver");
520 0 goto exit;
521 }
522
523 11559 result = globus_xio_attr_cntl(
524 attr, globus_i_soap_message_http_driver,
525 GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_METHOD,
526 "POST");
527 11559 if(result != GLOBUS_SUCCESS)
528 {
529 0 result = GlobusSoapMessageErrorFailedTransport(
530 result, "Failed to set request method in http driver");
531 0 goto exit;
532 }
533
534 11559 result = globus_xio_attr_cntl(attr,
535 globus_i_soap_message_tcp_driver,
536 GLOBUS_XIO_TCP_SET_NODELAY,
537 GLOBUS_TRUE);
538 11559 if(result != GLOBUS_SUCCESS)
539 {
540 0 result = GlobusSoapMessageErrorFailedTransport(
541 result, "Failed to set tcp nodelay.");
542 0 goto exit;
543 }
544
545
546 11559 result = globus_xio_register_open(
547 handle->xio_handle,
548 endpoint,
549 attr,
550 globus_l_soap_message_open_callback,
551 callback_handle);
552 11559 if(result != GLOBUS_SUCCESS)
553 {
554 0 result = GlobusSoapMessageErrorFailedTransport(
555 result, "Failed to connect to server");
556 0 goto exit;
557 }
558
559 11559 if(attr)
560 {
561 11559 globus_xio_attr_destroy(attr);
562 11559 attr = NULL;
563 }
564
565 11559 exit:
566
567 11559 if(result != GLOBUS_SUCCESS)
568 {
569 0 free(callback_handle);
570 0 if(attr)
571 {
572 0 globus_xio_attr_destroy(attr);
573 }
574 }
575 11559 if (quoted_soap_action != NULL)
576 {
577 11559 free(quoted_soap_action);
578 }
579
580 11559 GlobusSoapMessageDebugExit();
581 11559 return result;
582 }
583 /* globus_soap_message_register_open() */
584
585 /**
586 * Predicate to determine if the operation on this handle has been cancelled
587 * @ingroup globus_soap_message_transport
588 *
589 * @param handle
590 * SOAP message handle to query.
591 *
592 * @retval GLOBUS_TRUE
593 * The current I/O operation has been cancelled.
594 * @retval GLOBUS_FALSE
595 * The current I/O operation has not been cancelled.
596 */
597 globus_bool_t
598 globus_soap_message_is_cancelled(
599 globus_soap_message_handle_t handle)
600 11451 {
601 globus_bool_t cancelled;
602
603 11451 globus_mutex_lock(&handle->cancel_mutex);
604 11451 cancelled = handle->cancelled;
605 11451 globus_mutex_unlock(&handle->cancel_mutex);
606
607 11451 return cancelled;
608 }
609 /* globus_soap_message_is_cancelled() */
610
611 /**
612 * Cancel the current I/O operation on the SOAP message handle
613 * @ingroup globus_soap_message_transport
614 *
615 * @param handle
616 * SOAP message handle to cancel the operation on.
617 *
618 * @retval GLOBUS_SUCCESS
619 * Handle operations cancelled successfully.
620 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
621 * The @a handle parameter is NULL.
622 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT
623 * Unable to cancel the operation.
624 */
625 globus_result_t
626 globus_soap_message_cancel_message(
627 globus_soap_message_handle_t handle)
628 0 {
629 0 globus_result_t result = GLOBUS_SUCCESS;
630 GlobusFuncName(globus_soap_message_operations_cancel);
631 0 GlobusSoapMessageDebugEnter();
632
633 0 if (handle == NULL)
634 {
635 0 result = GlobusSoapMessageErrorNullParam;
636
637 0 goto exit;
638 }
639 0 result = globus_xio_handle_cancel_operations(
640 handle->xio_handle,
641 GLOBUS_XIO_CANCEL_OPEN|
642 GLOBUS_XIO_CANCEL_CLOSE|
643 GLOBUS_XIO_CANCEL_READ|
644 GLOBUS_XIO_CANCEL_WRITE);
645 0 if (result != GLOBUS_SUCCESS)
646 {
647 0 result = GlobusSoapMessageErrorFailedTransport(
648 result, "Failed to cancel message");
649 0 goto exit;
650 }
651
652 0 globus_mutex_lock(&handle->cancel_mutex);
653 0 handle->cancelled = 1;
654 0 globus_mutex_unlock(&handle->cancel_mutex);
655
656 0 exit:
657 0 return result;
658 }
659 /* globus_soap_message_cancel_message() */
660
661 /**
662 * Write the operation request to the service endpoint
663 * @ingroup globus_soap_message_transport
664 * Writes the serialized SOAP message associated with a SOAP handle to
665 * the service endpoint that the handle is connected to. This flushes all
666 * buffers that the handle is holding. When the message has been sent,
667 * the function pointed to by @a callback will be invoked.
668 *
669 * @param handle
670 * SOAP message handle to write the request on.
671 * @param callback
672 * Pointer to a function to be called when the write has completed.
673 * @param args
674 * Parameter to the @a callback function.
675 * @param response
676 * Flag indicating whether the caller expects a SOAP response.
677 *
678 *
679 * @retval GLOBUS_SUCCESS
680 * Write begun successfully.
681 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
682 * One of @a handle or @a callback is NULL.
683 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
684 * Insufficient memory to handle the write operation.
685 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT
686 * Unable to flush the buffers or write the message.
687 */
688 globus_result_t
689 globus_soap_message_register_write_request(
690 globus_soap_message_handle_t handle,
691 globus_soap_message_callback_func_t callback,
692 void * args,
693 globus_bool_t response)
694 11531 {
695 char content_length_buffer[100];
696 int buffer_length;
697 static unsigned char dummy_buffer[1];
698 globus_l_soap_message_callback_handle_t * callback_handle;
699 11531 globus_result_t result = GLOBUS_SUCCESS;
700 globus_xio_data_descriptor_t dd;
701 GlobusFuncName(globus_soap_message_register_write_request);
702 11531 GlobusSoapMessageDebugEnter();
703
704 11531 if (handle == NULL || callback == NULL)
705 {
706 0 result = GlobusSoapMessageErrorNullParam;
707
708 0 goto exit;
709 }
710 11531 callback_handle = malloc(sizeof(globus_l_soap_message_callback_handle_t));
711 11531 if(!callback_handle)
712 {
713 0 result = GlobusSoapMessageErrorOutOfMemory;
714 0 goto exit;
715 }
716
717 11531 callback_handle->callback = callback;
718 11531 callback_handle->args = args;
719 11531 callback_handle->message = handle;
720 11531 callback_handle->type = (response ? GLOBUS_SOAP_MESSAGE_REQUEST_CALLBACK:
721 GLOBUS_SOAP_MESSAGE_RESPONSE_CALLBACK);
722 11531 callback_handle->no_response = 0;
723
724 11531 if(callback_handle->message->writer)
725 {
726 11531 xmlFreeTextWriter(callback_handle->message->writer);
727 11531 callback_handle->message->writer = NULL;
728 }
729
730 11531 result = globus_xio_handle_cntl(
731 handle->xio_handle,
732 globus_i_soap_message_buffer_driver,
733 GLOBUS_XIO_BUFFER_GET_LENGTH,
734 &buffer_length);
735 11531 if(result != GLOBUS_SUCCESS)
736 {
737 0 result = GlobusSoapMessageErrorFailedTransport(
738 result, "Failed to set get length of message");
739 0 goto exit;
740 }
741
742 11531 content_length_buffer[0] = '\0';
743 11531 sprintf(content_length_buffer, "%d", buffer_length);
744
745 11531 result = globus_xio_handle_cntl(
746 handle->xio_handle,
747 globus_i_soap_message_http_driver,
748 GLOBUS_XIO_HTTP_HANDLE_SET_REQUEST_HEADER,
749 "Content-Length",
750 content_length_buffer);
751 11531 if(result != GLOBUS_SUCCESS)
752 {
753 0 result = GlobusSoapMessageErrorFailedTransport(
754 result, "Failed to set Content-Length in HTTP header");
755 0 goto exit;
756 }
757
758 11531 if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES))
759 {
760 char * buffer;
761 size_t read_length;
762
763 0 globus_xio_handle_cntl(
764 callback_handle->message->xio_handle,
765 globus_i_soap_message_buffer_driver,
766 GLOBUS_XIO_BUFFER_GET_MARKED_BUFFERS,
767 NULL, NULL, &buffer, &read_length);
768
769 0 GlobusSoapMessageDebugPrintf(
770 GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES,
771 ("----------------WRITING--------------\n%.*s\n"
772 "=====================================\n\n",
773 read_length, buffer));
774
775 0 free(buffer);
776 }
777
778 11531 result = globus_xio_data_descriptor_init(
779 &dd,
780 handle->xio_handle);
781
782 11531 if(result != GLOBUS_SUCCESS)
783 {
784 0 result = GlobusSoapMessageErrorFailedTransport(
785 result, "Failed to init data descriptor");
786 0 goto exit;
787 }
788
789 11531 result = globus_xio_data_descriptor_cntl(
790 dd,
791 globus_i_soap_message_buffer_driver,
792 GLOBUS_XIO_BUFFER_FLUSH);
793
794 11531 if(result != GLOBUS_SUCCESS)
795 {
796 0 result = GlobusSoapMessageErrorFailedTransport(
797 result, "Failed to set data descriptor to flush.");
798 0 goto exit;
799 }
800
801 11531 result = globus_xio_register_write(
802 handle->xio_handle,
803 dummy_buffer,
804 0,
805 0,
806 dd,
807 globus_l_soap_message_flush_callback,
808 callback_handle);
809
810 11531 if(result != GLOBUS_SUCCESS)
811 {
812 0 result = GlobusSoapMessageErrorFailedTransport(
813 result, "Failed to write message");
814 0 goto exit;
815 }
816 11531 globus_xio_data_descriptor_destroy(dd);
817
818 11531 exit:
819
820 11531 if(result != GLOBUS_SUCCESS)
821 {
822 0 if (GlobusDebugTrue(
823 GLOBUS_SOAP_MESSAGE,
824 GLOBUS_SOAP_MESSAGE_DEBUG_WARN))
825 {
826 char * errstr = globus_error_print_friendly(
827 0 globus_error_peek(result));
828 0 GlobusSoapMessageDebugPrintf(
829 GLOBUS_SOAP_MESSAGE_DEBUG_WARN,
830 ("Error writing request: %s\n", errstr));
831 0 free(errstr);
832 }
833
834 0 free(callback_handle);
835 }
836
837 11531 GlobusSoapMessageDebugExit();
838 11531 return result;
839 }
840 /* globus_soap_message_register_write_request() */
841
842 /**
843 * Write an operation response
844 * @ingroup globus_soap_message_transport
845 * Writes the serialized SOAP message associated with a SOAP handle to
846 * respond to an operation request. This flushes all
847 * buffers that the handle is holding. When the response has been sent,
848 * the function pointed to by @a callback will be invoked.
849 *
850 * @param handle
851 * SOAP message handle to write the request on.
852 * @param callback
853 * Pointer to a function to be called when the write has completed.
854 * @param args
855 * Parameter to the @a callback function.
856 *
857 * @retval GLOBUS_SUCCESS
858 * Write begun successfully.
859 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
860 * One of @a handle or @a callback is NULL.
861 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
862 * Insufficient memory to handle the write operation.
863 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT
864 * Unable to flush the buffers or write the message.
865 */
866 globus_result_t
867 globus_soap_message_register_write_response(
868 globus_soap_message_handle_t handle,
869 globus_soap_message_callback_func_t callback,
870 void * args)
871 10023 {
872 char content_length_buffer[100];
873 char * connection;
874 int buffer_length;
875 static unsigned char dummy_buffer[1];
876 globus_l_soap_message_callback_handle_t * callback_handle;
877 10023 globus_result_t result = GLOBUS_SUCCESS;
878 GlobusFuncName(globus_soap_message_register_write_response);
879 10023 GlobusSoapMessageDebugEnter();
880
881 10023 if (handle == NULL || callback == NULL)
882 {
883 0 result = GlobusSoapMessageErrorNullParam;
884
885 0 goto exit;
886 }
887 10023 callback_handle = malloc(sizeof(globus_l_soap_message_callback_handle_t));
888 10023 if(!callback_handle)
889 {
890 0 result = GlobusSoapMessageErrorOutOfMemory;
891 0 goto exit;
892 }
893 10023 callback_handle->callback = callback;
894 10023 callback_handle->args = args;
895 10023 callback_handle->message = handle;
896 10023 callback_handle->type = GLOBUS_SOAP_MESSAGE_RESPONSE_CALLBACK;
897 10023 callback_handle->no_response = 0;
898
899 10023 if(callback_handle->message->writer)
900 {
901 10023 xmlFreeTextWriter(callback_handle->message->writer);
902 10023 callback_handle->message->writer = NULL;
903 }
904
905 10023 result = globus_xio_handle_cntl(
906 handle->xio_handle,
907 globus_i_soap_message_buffer_driver,
908 GLOBUS_XIO_BUFFER_GET_LENGTH,
909 &buffer_length);
910 10023 if(result != GLOBUS_SUCCESS)
911 {
912 0 result = GlobusSoapMessageErrorFailedTransport(
913 result, "Failed to set get length of message");
914 0 goto exit;
915 }
916
917 10023 memset(content_length_buffer, 0, 100);
918 10023 sprintf(content_length_buffer, "%d", buffer_length);
919
920 10023 result = globus_xio_handle_cntl(
921 handle->xio_handle,
922 globus_i_soap_message_http_driver,
923 GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_HEADER,
924 "Content-Length",
925 content_length_buffer);
926 10023 if(result != GLOBUS_SUCCESS)
927 {
928 0 result = GlobusSoapMessageErrorFailedTransport(
929 result, "Failed to set Content-Length in HTTP header");
930 0 goto exit;
931 }
932
933 10023 connection = globus_soap_message_handle_get_attr(
934 handle,
935 GLOBUS_SOAP_MESSAGE_CONNECTION_KEY);
936
937 10023 if (connection && !strcmp(connection, "close"))
938 {
939 2 result = globus_xio_handle_cntl(
940 handle->xio_handle,
941 globus_i_soap_message_http_driver,
942 GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_HEADER,
943 "Connection",
944 "close");
945
946 2 if(result != GLOBUS_SUCCESS)
947 {
948 0 result = GlobusSoapMessageErrorFailedTransport(
949 result, "Failed to set Connection in HTTP header");
950 0 goto exit;
951 }
952 }
953
954 10023 if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES))
955 {
956 char * buffer;
957 size_t read_length;
958
959 0 globus_xio_handle_cntl(
960 callback_handle->message->xio_handle,
961 globus_i_soap_message_buffer_driver,
962 GLOBUS_XIO_BUFFER_GET_MARKED_BUFFERS,
963 NULL, NULL, &buffer, &read_length);
964
965 0 GlobusSoapMessageDebugPrintf(
966 GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES,
967 ("----------------WRITING--------------\n%.*s\n"
968 "=====================================\n\n",
969 read_length, buffer));
970
971 0 free(buffer);
972 }
973
974 10023 if(buffer_length > 0)
975 {
976 globus_xio_data_descriptor_t dd;
977
978 9933 GlobusSoapMessageDebugPrintf(
979 GLOBUS_SOAP_MESSAGE_DEBUG_DEBUG,
980 ("Writing %d byte response\n", buffer_length));
981
982 9933 result = globus_xio_data_descriptor_init(
983 &dd,
984 handle->xio_handle);
985
986 9933 if(result != GLOBUS_SUCCESS)
987 {
988 0 result = GlobusSoapMessageErrorFailedTransport(
989 result, "Failed to init data descriptor");
990 0 goto exit;
991 }
992
993 9933 result = globus_xio_data_descriptor_cntl(
994 dd,
995 globus_i_soap_message_buffer_driver,
996 GLOBUS_XIO_BUFFER_FLUSH);
997
998 9933 if(result != GLOBUS_SUCCESS)
999 {
1000 0 result = GlobusSoapMessageErrorFailedTransport(
1001 result, "Failed to set data descriptor to flush.");
1002 0 goto exit;
1003 }
1004
1005 9933 result = globus_xio_register_write(
1006 handle->xio_handle,
1007 dummy_buffer,
1008 0,
1009 0,
1010 dd,
1011 globus_l_soap_message_flush_callback,
1012 callback_handle);
1013
1014 9933 if(result != GLOBUS_SUCCESS)
1015 {
1016 0 result = GlobusSoapMessageErrorFailedTransport(
1017 result, "Failed to write message");
1018 0 goto exit;
1019 }
1020 }
1021 else
1022 {
1023 90 GlobusSoapMessageDebugPrintf(
1024 GLOBUS_SOAP_MESSAGE_DEBUG_DEBUG,
1025 ("Writing 0 byte response, just setting EoE\n"));
1026 90 globus_xio_handle_cntl(
1027 handle->xio_handle,
1028 globus_i_soap_message_http_driver,
1029 GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY);
1030
1031 90 callback_handle->callback(result, callback_handle->args);
1032
1033 90 free(callback_handle);
1034 90 callback_handle = NULL;
1035 }
1036
1037 10023 exit:
1038
1039 10023 if (result != GLOBUS_SUCCESS &&
1040 (GlobusDebugTrue(
1041 GLOBUS_SOAP_MESSAGE,
1042 GLOBUS_SOAP_MESSAGE_DEBUG_WARN)))
1043 {
1044 0 char * errstr = globus_error_print_friendly(globus_error_peek(result));
1045 0 GlobusSoapMessageDebugPrintf(
1046 GLOBUS_SOAP_MESSAGE_DEBUG_WARN,
1047 ("Error writing response: %s\n", errstr));
1048 0 free(errstr);
1049 }
1050 10023 if(result != GLOBUS_SUCCESS && callback_handle != NULL)
1051 {
1052 0 free(callback_handle);
1053 }
1054
1055 10023 GlobusSoapMessageDebugExit();
1056 10023 return result;
1057 }
1058 /* globus_soap_message_register_write_response() */
1059
1060 /**
1061 * Register a read of an operation response
1062 * @ingroup globus_soap_message_transport
1063 * Registers a new read with the I/O system to receive a SOAP response
1064 * message. The @a callback function will be invoked when the message
1065 * is ready.
1066 *
1067 * @param handle
1068 * SOAP message handle to read the response from.
1069 * @param callback
1070 * Pointer to a function to be called when the write has completed.
1071 * @param args
1072 * Parameter to the @a callback function.
1073 *
1074 * @retval GLOBUS_SUCCESS
1075 * Read begun successfully.
1076 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1077 * One of @a handle or @a callback is NULL.
1078 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
1079 * Insufficient memory to handle the read operation.
1080 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT
1081 * Unable to register the read operation.
1082 */
1083 globus_result_t
1084 globus_soap_message_register_read_response(
1085 globus_soap_message_handle_t handle,
1086 globus_soap_message_callback_func_t callback,
1087 void * args)
1088 11451 {
1089 globus_l_soap_message_callback_handle_t * callback_handle;
1090 11451 globus_result_t result = GLOBUS_SUCCESS;
1091 GlobusFuncName(globus_soap_message_register_read_response);
1092 11451 GlobusSoapMessageDebugEnter();
1093
1094 11451 if (handle == NULL || callback == NULL)
1095 {
1096 0 result = GlobusSoapMessageErrorNullParam;
1097
1098 0 goto exit;
1099 }
1100
1101 11451 callback_handle = malloc(sizeof(globus_l_soap_message_callback_handle_t));
1102 11451 if(!callback_handle)
1103 {
1104 0 result = GlobusSoapMessageErrorOutOfMemory;
1105 0 goto exit;
1106 }
1107
1108 11451 callback_handle->callback = callback;
1109 11451 callback_handle->args = args;
1110 11451 callback_handle->message = handle;
1111 11451 callback_handle->no_response = 0;
1112
1113 11451 globus_mutex_lock(&handle->mutex);
1114 11451 handle->response_semaphore++;
1115
1116 11451 if(handle->response_semaphore > 1)
1117 {
1118 0 globus_mutex_unlock(&handle->mutex);
1119 0 result = globus_callback_register_oneshot(
1120 NULL,
1121 &globus_i_reltime_zero,
1122 globus_l_soap_message_response_callback,
1123 callback_handle);
1124 0 if(result != GLOBUS_SUCCESS)
1125 {
1126 0 result = GlobusSoapMessageErrorFailedTransport(
1127 result, "Failed to register periodic callbcak for response");
1128 0 goto exit;
1129 }
1130 }
1131 else
1132 {
1133 11451 globus_mutex_unlock(&handle->mutex);
1134 11451 handle->response_handle = (void *)callback_handle;
1135 }
1136
1137 11451 exit:
1138
1139 11451 GlobusSoapMessageDebugExit();
1140 11451 return result;
1141 }
1142 /* globus_soap_message_register_read_response() */
1143
1144 /**
1145 * Register a read of an operation response
1146 * @ingroup globus_soap_message_transport
1147 * Registers a new read with the I/O system to receive a SOAP request
1148 * message. The @a callback function will be invoked when the message
1149 * is ready.
1150 *
1151 * @param handle
1152 * SOAP message handle to read the request from.
1153 * @param callback
1154 * Pointer to a function to be called when the write has completed.
1155 * @param args
1156 * Parameter to the @a callback function.
1157 *
1158 * @retval GLOBUS_SUCCESS
1159 * Read begun successfully.
1160 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1161 * One of @a handle or @a callback is NULL.
1162 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
1163 * Insufficient memory to handle the read operation.
1164 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT
1165 * Unable to register the read operation.
1166 */
1167 globus_result_t
1168 globus_soap_message_register_read_request(
1169 globus_soap_message_handle_t handle,
1170 globus_soap_message_callback_func_t callback,
1171 void * args)
1172 10023 {
1173 globus_l_soap_message_callback_handle_t * callback_handle;
1174 10023 globus_result_t result = GLOBUS_SUCCESS;
1175 GlobusFuncName(globus_soap_message_register_read_request);
1176 10023 GlobusSoapMessageDebugEnter();
1177
1178 10023 if (handle == NULL || callback == NULL)
1179 {
1180 0 result = GlobusSoapMessageErrorNullParam;
1181 0 goto exit;
1182 }
1183 10023 callback_handle = malloc(sizeof(globus_l_soap_message_callback_handle_t));
1184 10023 if(!callback_handle)
1185 {
1186 0 result = GlobusSoapMessageErrorOutOfMemory;
1187 0 goto exit;
1188 }
1189
1190 10023 callback_handle->callback = callback;
1191 10023 callback_handle->args = args;
1192 10023 callback_handle->message = handle;
1193 10023 callback_handle->no_response = 0;
1194
1195 10023 result = globus_xio_handle_cntl(
1196 callback_handle->message->xio_handle,
1197 globus_i_soap_message_buffer_driver,
1198 GLOBUS_XIO_BUFFER_ENABLE_READ_BUFFERING);
1199 10023 if(result != GLOBUS_SUCCESS)
1200 {
1201 0 result = GlobusSoapMessageErrorFailedTransport(
1202 result, "Failed to enable read buffering in buffer driver");
1203 0 goto exit;
1204 }
1205
1206 10023 result = globus_xio_register_read(
1207 handle->xio_handle,
1208 (globus_byte_t *)handle->readbuf,
1209 GLOBUS_I_SOAP_MESSAGE_READBUF_SIZE,
1210 1,
1211 NULL,
1212 globus_l_soap_message_read_callback,
1213 callback_handle);
1214 10023 if(result != GLOBUS_SUCCESS)
1215 {
1216 0 result = GlobusSoapMessageErrorFailedTransport(
1217 result, "Failed to begin reading SOAP message");
1218 0 goto exit;
1219 }
1220
1221 10023 exit:
1222
1223 10023 GlobusSoapMessageDebugExit();
1224 10023 return result;
1225 }
1226 /* globus_soap_message_register_read_request() */
1227
1228 /**
1229 * Close the I/O handle associated with a SOAP operation
1230 * @ingroup globus_soap_message_transport
1231 * Registers a close of the I/O handle which has been used to process
1232 * a SOAP request or response. The @a callback function will be invoked when
1233 * the handle is closed.
1234 *
1235 * @param handle
1236 * SOAP message handle to read the request from.
1237 * @param callback
1238 * Pointer to a function to be called when the write has completed.
1239 * @param args
1240 * Parameter to the @a callback function.
1241 *
1242 * @retval GLOBUS_SUCCESS
1243 * Read begun successfully.
1244 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1245 * One of @a handle or @a callback is NULL.
1246 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
1247 * Insufficient memory to handle the read operation.
1248 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT
1249 * Unable to register the read operation.
1250 */
1251 globus_result_t
1252 globus_soap_message_register_close(
1253 globus_soap_message_handle_t handle,
1254 globus_soap_message_callback_func_t callback,
1255 void * args)
1256 16522 {
1257 16522 globus_result_t result = GLOBUS_SUCCESS;
1258 globus_l_soap_message_close_callback_t * callback_handle;
1259 GlobusFuncName(globus_soap_message_register_close);
1260 16522 GlobusSoapMessageDebugEnter();
1261
1262 16522 if(handle->reader)
1263 {
1264 11449 xmlFreeTextReader(handle->reader);
1265 }
1266 16522 handle->reader = NULL;
1267 16522 if (handle->doc_to_free)
1268 {
1269 11443 xmlFreeDoc(handle->doc_to_free);
1270 11443 handle->doc_to_free = NULL;
1271 }
1272
1273 16522 callback_handle = globus_malloc(
1274 sizeof(globus_l_soap_message_close_callback_t));
1275 16522 if(!callback_handle)
1276 {
1277 0 result = GlobusSoapMessageErrorOutOfMemory;
1278 0 goto exit;
1279 }
1280 16522 callback_handle->callback = callback;
1281 16522 callback_handle->args = args;
1282
1283 16522 result = globus_xio_register_close(
1284 handle->xio_handle,
1285 NULL,
1286 globus_l_soap_message_register_close_callback,
1287 callback_handle);
1288
1289 16522 handle->xio_handle = NULL;
1290
1291 16522 exit:
1292 16522 GlobusSoapMessageDebugExit();
1293 16522 return result;
1294 }
1295 /* globus_soap_message_register_close() */
1296
1297 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
1298 globus_result_t
1299 globus_i_soap_message_setup_unbuffered_writer(
1300 globus_soap_message_handle_t message)
1301 493 {
1302 493 xmlOutputBufferPtr output_buffer = NULL;
1303 493 globus_result_t result = GLOBUS_SUCCESS;
1304 GlobusFuncName(globus_i_soap_message_setup_unbuffered_writer);
1305 493 GlobusSoapMessageDebugEnter();
1306
1307 493 output_buffer = xmlOutputBufferCreateIO(
1308 globus_l_soap_message_handle_libxml_io_write_callback,
1309 globus_l_soap_message_handle_libxml_io_close_callback,
1310 message,
1311 0);
1312 493 if(!output_buffer)
1313 {
1314 0 result = GlobusSoapMessageErrorInitFailed(
1315 "Failed to initialize output buffer");
1316 0 goto exit;
1317 }
1318
1319 493 message->writer = xmlNewTextWriter(output_buffer);
1320 493 if(!message->writer)
1321 {
1322 0 result = GlobusSoapMessageErrorInitFailed(
1323 "Failed to initialize xmlWriter");
1324 0 goto free_output;
1325 }
1326
1327 493 goto exit;
1328
1329 0 free_output:
1330
1331 0 xmlOutputBufferClose(output_buffer);
1332
1333 493 exit:
1334
1335 493 GlobusSoapMessageDebugExit();
1336 493 return result;
1337 }
1338
1339
1340 globus_result_t
1341 globus_i_soap_message_reset_reader(
1342 globus_soap_message_handle_t handle)
1343 5230 {
1344 5230 globus_result_t result = GLOBUS_SUCCESS;
1345 GlobusFuncName(globus_i_soap_message_reset_reader);
1346 5230 GlobusSoapMessageDebugEnter();
1347
1348 5230 if(handle->reader)
1349 {
1350 0 xmlFreeTextReader(handle->reader);
1351 }
1352 5230 if (handle->doc_to_free)
1353 {
1354 0 xmlFreeDoc(handle->doc_to_free);
1355 0 handle->doc_to_free = NULL;
1356 }
1357
1358 5230 handle->buffer_eof = 0;
1359
1360 5230 handle->reader = xmlReaderForIO(
1361 globus_l_soap_message_handle_libxml_io_read_callback,
1362 globus_l_soap_message_handle_libxml_io_close_callback,
1363 handle,
1364 NULL,
1365 NULL,
1366 0);
1367 5230 if(!handle->reader)
1368 {
1369 0 result = GlobusSoapMessageErrorInitFailed(
1370 "Failed to initialize xmlReader");
1371 0 goto exit;
1372 }
1373
1374 5230 xmlTextReaderSetErrorHandler(handle->reader,
1375 globus_i_soap_message_error_callback,
1376 handle);
1377
1378 5230 xmlTextReaderSetStructuredErrorHandler(
1379 handle->reader,
1380 globus_i_soap_message_structured_error_callback,
1381 handle);
1382
1383 5230 exit:
1384
1385 5230 GlobusSoapMessageDebugExit();
1386 5230 return result;
1387 }
1388
1389 globus_result_t
1390 globus_i_soap_message_setup_transport_security(
1391 globus_soap_message_attr_t attrs,
1392 globus_xio_attr_t xio_attr)
1393 5053 {
1394 globus_xio_gsi_authorization_mode_t gsi_authz;
1395 globus_soap_message_auth_protection_level_t protect;
1396 globus_soap_message_authz_method_t authz;
1397 void * credential;
1398 void * target_name;
1399 5053 globus_result_t result = GLOBUS_SUCCESS;
1400 GlobusFuncName(globus_l_soap_message_setup_transport_security);
1401 5053 GlobusSoapMessageDebugEnter();
1402
1403 5053 credential = globus_soap_message_attr_get(
1404 attrs,
1405 GLOBUS_SOAP_MESSAGE_USER_CREDENTIAL_KEY);
1406 5053 if(credential)
1407 {
1408 0 result = globus_xio_attr_cntl(
1409 xio_attr,
1410 globus_i_soap_message_gsi_driver,
1411 GLOBUS_XIO_GSI_SET_CREDENTIAL,
1412 credential);
1413 0 if(result != GLOBUS_SUCCESS)
1414 {
1415 0 result = GlobusSoapMessageErrorFailedTransport(
1416 result, "Failed to set credential for gsi driver");
1417 0 goto exit;
1418 }
1419 }
1420
1421 5053 result = globus_xio_attr_cntl(
1422 xio_attr,
1423 globus_i_soap_message_gsi_driver,
1424 GLOBUS_XIO_GSI_SET_DELEGATION_MODE,
1425 GLOBUS_XIO_GSI_DELEGATION_MODE_NONE);
1426 5053 if(result != GLOBUS_SUCCESS)
1427 {
1428 0 result = GlobusSoapMessageErrorFailedTransport(
1429 result, "Failed to set delegation mode for gsi driver");
1430 0 goto exit;
1431 }
1432
1433 5053 result = globus_xio_attr_cntl(
1434 xio_attr,
1435 globus_i_soap_message_gsi_driver,
1436 GLOBUS_XIO_GSI_SET_SSL_COMPATIBLE,
1437 1);
1438 5053 if(result != GLOBUS_SUCCESS)
1439 {
1440 0 result = GlobusSoapMessageErrorFailedTransport(
1441 result, "Failed to set delegation mode for gsi driver");
1442 0 goto exit;
1443 }
1444
1445 5053 protect =
1446 (globus_soap_message_auth_protection_level_t)
1447 globus_soap_message_attr_get(
1448 attrs,
1449 GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_KEY);
1450 5053 if(protect != GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_NOT_SET)
1451 {
1452 0 result = globus_xio_attr_cntl(
1453 xio_attr,
1454 globus_i_soap_message_gsi_driver,
1455 GLOBUS_XIO_GSI_SET_PROTECTION_LEVEL,
1456 ((protect == GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_INTEGRITY) ?
1457 GLOBUS_XIO_GSI_PROTECTION_LEVEL_INTEGRITY :
1458 GLOBUS_XIO_GSI_PROTECTION_LEVEL_PRIVACY));
1459 0 if(result != GLOBUS_SUCCESS)
1460 {
1461 0 result = GlobusSoapMessageErrorFailedTransport(
1462 result, "Failed to set delegation mode for gsi driver");
1463 0 goto exit;
1464 }
1465 }
1466
1467 5053 authz =
1468 (globus_soap_message_authz_method_t)
1469 globus_soap_message_attr_get(
1470 attrs,
1471 GLOBUS_SOAP_MESSAGE_AUTHZ_METHOD_KEY);
1472
1473 5053 switch(authz)
1474 {
1475 case GLOBUS_SOAP_MESSAGE_AUTHZ_SELF:
1476 0 gsi_authz = GLOBUS_XIO_GSI_SELF_AUTHORIZATION;
1477 0 break;
1478 case GLOBUS_SOAP_MESSAGE_AUTHZ_IDENTITY:
1479 0 gsi_authz = GLOBUS_XIO_GSI_IDENTITY_AUTHORIZATION;
1480 0 break;
1481 case GLOBUS_SOAP_MESSAGE_AUTHZ_HOST:
1482 0 gsi_authz = GLOBUS_XIO_GSI_HOST_AUTHORIZATION;
1483 0 break;
1484 case GLOBUS_SOAP_MESSAGE_AUTHZ_HOST_SELF:
1485 /* Will authorize after connection is established */
1486 case GLOBUS_SOAP_MESSAGE_AUTHZ_NONE:
1487 5053 gsi_authz = GLOBUS_XIO_GSI_NO_AUTHORIZATION;
1488 break;
1489 }
1490
1491 5053 result = globus_xio_attr_cntl(
1492 xio_attr,
1493 globus_i_soap_message_gsi_driver,
1494 GLOBUS_XIO_GSI_SET_AUTHORIZATION_MODE,
1495 gsi_authz);
1496 5053 if(result != GLOBUS_SUCCESS)
1497 {
1498 0 result = GlobusSoapMessageErrorFailedTransport(
1499 result, "Failed to set delegation mode for gsi driver");
1500 0 goto exit;
1501 }
1502
1503 5053 target_name = globus_soap_message_attr_get(
1504 attrs,
1505 GLOBUS_SOAP_MESSAGE_AUTHZ_TARGET_NAME_KEY);
1506 5053 if(target_name)
1507 {
1508 0 result = globus_xio_attr_cntl(
1509 xio_attr,
1510 globus_i_soap_message_gsi_driver,
1511 GLOBUS_XIO_GSI_SET_TARGET_NAME,
1512 target_name);
1513 0 if(result != GLOBUS_SUCCESS)
1514 {
1515 0 result = GlobusSoapMessageErrorFailedTransport(
1516 result, "Failed to set target name on gsi driver");
1517 0 goto exit;
1518 }
1519 }
1520
1521 5053 if (globus_soap_message_attr_get(attrs, GLOBUS_SOAP_MESSAGE_AUTH_ANONYMOUS_KEY))
1522 {
1523 0 result = globus_xio_attr_cntl(
1524 xio_attr,
1525 globus_i_soap_message_gsi_driver,
1526 GLOBUS_XIO_GSI_SET_ANON);
1527 0 if(result != GLOBUS_SUCCESS)
1528 {
1529 0 result = GlobusSoapMessageErrorFailedTransport(
1530 result, "Failed to set target name on gsi driver");
1531 0 goto exit;
1532 }
1533 }
1534
1535 5053 exit:
1536
1537 5053 GlobusSoapMessageDebugExit();
1538 5053 return result;
1539 }
1540
1541 void
1542 globus_i_soap_message_error_callback(
1543 void * arg,
1544 const char * msg,
1545 xmlParserSeverities severity,
1546 xmlTextReaderLocatorPtr locator)
1547 0 {
1548 globus_soap_message_handle_t handle;
1549 int lno;
1550 xmlChar * baseuri;
1551 GlobusFuncName(globus_i_soap_message_error_callback);
1552 0 GlobusSoapMessageDebugEnter();
1553
1554 0 handle = (globus_soap_message_handle_t) arg;
1555 0 if(handle->result != GLOBUS_SUCCESS)
1556 {
1557 0 return;
1558 }
1559
1560 0 if(locator)
1561 {
1562 0 lno = xmlTextReaderLocatorLineNumber(locator);
1563 0 baseuri = xmlTextReaderLocatorBaseURI(locator);
1564 }
1565
1566 0 switch(severity)
1567 {
1568 case XML_PARSER_SEVERITY_ERROR:
1569 case XML_PARSER_SEVERITY_VALIDITY_ERROR:
1570
1571 0 handle->result = GlobusSoapMessageErrorParserFailed(msg, lno, baseuri);
1572 0 break;
1573
1574 case XML_PARSER_SEVERITY_WARNING:
1575 case XML_PARSER_SEVERITY_VALIDITY_WARNING:
1576
1577 0 GlobusSoapMessageDebugPrintf(GLOBUS_SOAP_MESSAGE_DEBUG_WARN,
1578 ("%s:%d: %s", baseuri, lno, msg));
1579
1580 default:
1581 break;
1582 }
1583
1584 0 GlobusSoapMessageDebugExit();
1585 }
1586 /* globus_i_soap_message_error_callback() */
1587
1588 void
1589 globus_i_soap_message_structured_error_callback(
1590 void * userdata,
1591 xmlErrorPtr error)
1592 24 {
1593 globus_soap_message_handle_t handle;
1594 GlobusFuncName(globus_i_soap_message_structured_error_callback);
1595 24 GlobusSoapMessageDebugEnter();
1596
1597 24 handle = (globus_soap_message_handle_t) userdata;
1598
1599 24 if(handle->result != GLOBUS_SUCCESS)
1600 {
1601 12 return;
1602 }
1603
1604 12 handle->result = GlobusSoapMessageErrorParserFailed(
1605 error->message, error->line, error->file);
1606
1607 12 GlobusSoapMessageDebugExit();
1608 }
1609
1610 static
1611 int
1612 globus_l_soap_message_handle_libxml_io_read_callback(
1613 void * context,
1614 char * buffer,
1615 int length)
1616 297594 {
1617 297594 globus_size_t read_length = 0;
1618 globus_soap_message_handle_t handle;
1619 297594 globus_result_t result = GLOBUS_SUCCESS;
1620 GlobusFuncName(
1621 globus_l_soap_message_handle_libxml_io_read_callback);
1622 297594 GlobusSoapMessageDebugEnter();
1623
1624 297594 handle = (globus_soap_message_handle_t) context;
1625 297594 globus_assert_string(handle, "NULL handle passed to function");
1626
1627 297594 if(handle->buffer_eof)
1628 {
1629 21018 goto exit;
1630 }
1631
1632 276576 result = globus_xio_read(
1633 handle->xio_handle, (globus_byte_t *)buffer,
1634 length, 1, &read_length, NULL);
1635 298044 if(result != GLOBUS_SUCCESS &&
1636 globus_xio_driver_error_match(
1637 globus_i_soap_message_buffer_driver,
1638 globus_error_peek(result),
1639 GLOBUS_XIO_BUFFER_ERROR_EOF))
1640 {
1641 21468 handle->result = GLOBUS_SUCCESS;
1642 21468 handle->buffer_eof = 1;
1643 }
1644 255108 else if(result != GLOBUS_SUCCESS)
1645 {
1646 293 handle->result = result;
1647 }
1648
1649 297594 exit:
1650
1651 297594 GlobusSoapMessageDebugExit();
1652 297594 return read_length;
1653 }
1654
1655 static
1656 int
1657 globus_l_soap_message_handle_libxml_io_write_callback(
1658 void * context,
1659 const char * buffer,
1660 int length)
1661 322865 {
1662 322865 globus_size_t bytes_written = 0;
1663 322865 globus_result_t result = GLOBUS_SUCCESS;
1664 globus_soap_message_handle_t handle;
1665 GlobusFuncName(
1666 globus_l_soap_message_handle_libxml_io_write_callback);
1667 322865 GlobusSoapMessageDebugEnter();
1668
1669 322865 handle = (globus_soap_message_handle_t) context;
1670 322865 globus_assert_string(handle, "NULL handle passed to function");
1671
1672 322865 result = globus_xio_write(
1673 handle->xio_handle, (globus_byte_t *) buffer,
1674 length, length, &bytes_written, NULL);
1675 322865 if(result != GLOBUS_SUCCESS)
1676 {
1677 0 handle->result = result;
1678 }
1679
1680 322865 GlobusSoapMessageDebugExit();
1681 322865 return bytes_written;
1682 }
1683
1684 static
1685 int
1686 globus_l_soap_message_handle_libxml_io_close_callback(
1687 void * context)
1688 48747 {
1689 globus_soap_message_handle_t handle;
1690 GlobusFuncName(
1691 globus_l_soap_message_handle_libxml_io_close_callback);
1692 48747 GlobusSoapMessageDebugEnter();
1693
1694 48747 handle = (globus_soap_message_handle_t) context;
1695 48747 globus_assert_string(handle, "NULL handle passed to function");
1696
1697 /* do nothing. close should be done async. */
1698
1699 48747 GlobusSoapMessageDebugExit();
1700 48747 return 0;
1701 }
1702
1703 static
1704 void
1705 globus_l_soap_message_open_callback(
1706 globus_xio_handle_t handle,
1707 globus_result_t result,
1708 void * user_args)
1709 11559 {
1710 globus_soap_message_auth_method_t authn;
1711 globus_soap_message_authz_method_t authz;
1712 globus_l_soap_message_callback_handle_t * callback_handle;
1713
1714 11559 callback_handle = (globus_l_soap_message_callback_handle_t *) user_args;
1715
1716 11559 if(result == GLOBUS_SUCCESS)
1717 {
1718 11531 authn = (globus_soap_message_auth_method_t)
1719 globus_soap_message_attr_get(
1720 callback_handle->message->attrs,
1721 GLOBUS_SOAP_MESSAGE_AUTHENTICATION_METHOD_KEY);
1722
1723 11531 authz = (globus_soap_message_authz_method_t)
1724 globus_soap_message_attr_get(
1725 callback_handle->message->attrs,
1726 GLOBUS_SOAP_MESSAGE_AUTHZ_METHOD_KEY);
1727 11531 if (authn == GLOBUS_SOAP_MESSAGE_AUTH_SECURE &&
1728 authz == GLOBUS_SOAP_MESSAGE_AUTHZ_HOST_SELF)
1729 {
1730 0 result = globus_l_authz_host_self(callback_handle->message, authn);
1731
1732 0 if (result != GLOBUS_SUCCESS)
1733 {
1734 0 goto exit;
1735 }
1736 }
1737 11531 result = globus_soap_message_setup_writer(
1738 callback_handle->message);
1739 11531 if(result != GLOBUS_SUCCESS)
1740 {
1741 0 goto exit;
1742 }
1743 }
1744 else
1745 {
1746 28 callback_handle->message->result = result;
1747 }
1748
1749
1750 11559 exit:
1751
1752 11559 callback_handle->callback(result, callback_handle->args);
1753 11559 free(callback_handle);
1754 11559 }
1755
1756 static
1757 void
1758 globus_l_soap_message_flush_callback(
1759 globus_xio_handle_t handle,
1760 globus_result_t result,
1761 globus_byte_t * buffer,
1762 globus_size_t len,
1763 globus_size_t nbytes,
1764 globus_xio_data_descriptor_t data_desc,
1765 void * user_args)
1766 21464 {
1767 21464 globus_result_t internal_result = GLOBUS_SUCCESS;
1768 static globus_byte_t fake_buffer[1];
1769 globus_l_soap_message_callback_handle_t * callback_handle;
1770
1771 21464 callback_handle = (globus_l_soap_message_callback_handle_t *) user_args;
1772 21464 callback_handle->message->result = result;
1773
1774 21464 if(nbytes > 0)
1775 {
1776 21464 internal_result = globus_xio_handle_cntl(
1777 callback_handle->message->xio_handle,
1778 globus_i_soap_message_http_driver,
1779 GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY);
1780 21464 if(internal_result != GLOBUS_SUCCESS)
1781 {
1782 0 internal_result = GlobusSoapMessageErrorFailedTransport(
1783 internal_result,
1784 "Failed to flush message");
1785 0 goto error;
1786 }
1787 }
1788
1789 21464 internal_result = globus_xio_handle_cntl(
1790 callback_handle->message->xio_handle,
1791 globus_i_soap_message_buffer_driver,
1792 GLOBUS_XIO_BUFFER_CLEAR);
1793 21464 if(internal_result != GLOBUS_SUCCESS)
1794 {
1795 0 internal_result = GlobusSoapMessageErrorFailedTransport(
1796 internal_result,
1797 "Failed to flush message");
1798 0 goto error;
1799 }
1800
1801 21464 callback_handle->callback(result, callback_handle->args);
1802
1803 21464 if (result != GLOBUS_SUCCESS)
1804 {
1805 0 goto exit;
1806 }
1807
1808 32915 if (callback_handle->type == GLOBUS_SOAP_MESSAGE_REQUEST_CALLBACK &&
1809 callback_handle->no_response == 0)
1810 {
1811 11451 result = globus_xio_register_read(handle,
1812 fake_buffer,
1813 0,
1814 0,
1815 NULL,
1816 globus_l_soap_message_response_ready_callback,
1817 callback_handle->message);
1818
1819 11451 if(result != GLOBUS_SUCCESS)
1820 {
1821 0 globus_l_soap_message_response_ready_callback(
1822 handle,
1823 result,
1824 fake_buffer,
1825 0,
1826 0,
1827 NULL,
1828 callback_handle->message);
1829 }
1830 }
1831 else
1832 {
1833 10013 globus_assert(
1834 callback_handle->type == GLOBUS_SOAP_MESSAGE_RESPONSE_CALLBACK ||
1835 callback_handle->no_response);
1836 }
1837
1838 21464 goto exit;
1839
1840 0 error:
1841 0 callback_handle->callback(internal_result, callback_handle->args);
1842
1843 21464 exit:
1844 21464 free(callback_handle);
1845 21464 }
1846
1847 static
1848 void
1849 globus_l_soap_message_read_callback(
1850 globus_xio_handle_t handle,
1851 globus_result_t result,
1852 globus_byte_t * buffer,
1853 globus_size_t len,
1854 globus_size_t nbytes,
1855 globus_xio_data_descriptor_t data_desc,
1856 void * user_arg)
1857 1998092 {
1858 globus_l_soap_message_callback_handle_t * callback_handle;
1859 1998092 globus_result_t local_result = GLOBUS_SUCCESS;
1860 GlobusFuncName(globus_l_soap_message_read_callback);
1861 1998092 GlobusSoapMessageDebugEnter();
1862
1863 1998092 callback_handle = (globus_l_soap_message_callback_handle_t *) user_arg;
1864 1998092 callback_handle->message->result = result;
1865
1866 1998092 if(result != GLOBUS_SUCCESS)
1867 {
1868 42940 if(globus_xio_error_is_eof(result) ||
1869 globus_xio_driver_error_match(
1870 globus_i_soap_message_http_driver,
1871 globus_error_peek(result), GLOBUS_XIO_HTTP_ERROR_EOF) ||
1872 globus_xio_driver_error_match(
1873 globus_i_soap_message_buffer_driver,
1874 globus_error_peek(result), GLOBUS_XIO_BUFFER_ERROR_EOF))
1875 {
1876 21470 result = GLOBUS_SUCCESS;
1877
1878 21470 if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES))
1879 {
1880 char * buffer;
1881 size_t read_length;
1882
1883 0 globus_xio_handle_cntl(
1884 callback_handle->message->xio_handle,
1885 globus_i_soap_message_buffer_driver,
1886 GLOBUS_XIO_BUFFER_GET_MARKED_BUFFERS,
1887 NULL, NULL, &buffer, &read_length);
1888
1889 0 GlobusSoapMessageDebugPrintf(
1890 GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES,
1891 ("----------------READING--------------\n%.*s\n"
1892 "=====================================\n\n",
1893 read_length, buffer));
1894
1895 0 free(buffer);
1896 }
1897
1898 21470 local_result = globus_xio_handle_cntl(
1899 callback_handle->message->xio_handle,
1900 globus_i_soap_message_buffer_driver,
1901 GLOBUS_XIO_BUFFER_RESET_READ_POSITION);
1902 21470 if(local_result != GLOBUS_SUCCESS)
1903 {
1904 0 local_result = GlobusSoapMessageErrorFailedTransport(
1905 local_result,
1906 "failed to reset buffer read position to start");
1907 0 goto exit;
1908 }
1909
1910 21470 if (callback_handle->message->reader != NULL)
1911 {
1912 4937 xmlFreeTextReader(callback_handle->message->reader);
1913 }
1914 21470 if (callback_handle->message->doc_to_free != NULL)
1915 {
1916 0 xmlFreeDoc(callback_handle->message->doc_to_free);
1917 0 callback_handle->message->doc_to_free = NULL;
1918 }
1919 21470 callback_handle->message->reader = xmlReaderForIO(
1920 globus_l_soap_message_handle_libxml_io_read_callback,
1921 globus_l_soap_message_handle_libxml_io_close_callback,
1922 callback_handle->message,
1923 NULL,
1924 NULL,
1925 0);
1926 21470 if(!callback_handle->message->reader)
1927 {
1928 0 result = GlobusSoapMessageErrorInitFailed(
1929 "Failed to initialize xmlReader");
1930 0 goto exit;
1931 }
1932
1933 21470 xmlTextReaderSetErrorHandler(callback_handle->message->reader,
1934 globus_i_soap_message_error_callback,
1935 callback_handle->message);
1936
1937 21470 xmlTextReaderSetStructuredErrorHandler(
1938 callback_handle->message->reader,
1939 globus_i_soap_message_structured_error_callback,
1940 callback_handle->message);
1941
1942 21470 callback_handle->callback(result, callback_handle->args);
1943 21470 free(callback_handle);
1944 }
1945 else
1946 {
1947 0 local_result = result;
1948 }
1949
1950 21470 goto exit;
1951 }
1952
1953 1976622 local_result = globus_xio_register_read(
1954 callback_handle->message->xio_handle,
1955 (globus_byte_t *)callback_handle->message->readbuf,
1956 GLOBUS_I_SOAP_MESSAGE_READBUF_SIZE,
1957 1,
1958 NULL,
1959 globus_l_soap_message_read_callback,
1960 callback_handle);
1961 1976622 if(local_result != GLOBUS_SUCCESS)
1962 {
1963 0 local_result = GlobusSoapMessageErrorFailedTransport(
1964 local_result, "Failed to begin reading SOAP message");
1965 0 goto exit;
1966 }
1967
1968 1998092 exit:
1969
1970 1998092 if(local_result != GLOBUS_SUCCESS)
1971 {
1972 0 callback_handle->message->result = local_result;
1973 0 callback_handle->callback(result, callback_handle->args);
1974 }
1975
1976 1998092 GlobusSoapMessageDebugExit();
1977 return;
1978 }
1979
1980 static
1981 void
1982 globus_l_soap_message_response_callback(
1983 void * args)
1984 11451 {
1985 11451 globus_result_t result = GLOBUS_SUCCESS;
1986 globus_l_soap_message_callback_handle_t * callback_handle;
1987 GlobusFuncName(globus_l_soap_message_response_callback);
1988 11451 GlobusSoapMessageDebugEnter();
1989
1990 11451 callback_handle = (globus_l_soap_message_callback_handle_t *) args;
1991
1992 11451 if(callback_handle->message->response_semaphore >= 2)
1993 {
1994 11451 globus_mutex_lock(&callback_handle->message->mutex);
1995 11451 callback_handle->message->response_semaphore = 0;
1996 11451 globus_mutex_unlock(&callback_handle->message->mutex);
1997
1998 11451 if(callback_handle->message->result != GLOBUS_SUCCESS)
1999 {
2000 10 if (globus_error_match
2001 (globus_error_peek(
2002 callback_handle->message->result),
2003 GLOBUS_SOAP_MESSAGE_MODULE,
2004 GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT))
2005 {
2006 4 result = callback_handle->message->result;
2007 4 goto exit;
2008 }
2009 }
2010 11447 result = globus_xio_handle_cntl(
2011 callback_handle->message->xio_handle,
2012 globus_i_soap_message_buffer_driver,
2013 GLOBUS_XIO_BUFFER_ENABLE_READ_BUFFERING);
2014 11447 if(result != GLOBUS_SUCCESS)
2015 {
2016 0 result = GlobusSoapMessageErrorFailedTransport(
2017 result, "Failed to enable read buffering in buffer driver");
2018 0 goto exit;
2019 }
2020
2021 11447 result = globus_xio_register_read(
2022 callback_handle->message->xio_handle,
2023 (globus_byte_t *)callback_handle->message->readbuf,
2024 GLOBUS_I_SOAP_MESSAGE_READBUF_SIZE,
2025 1,
2026 NULL,
2027 globus_l_soap_message_read_callback,
2028 callback_handle);
2029 11447 if(result != GLOBUS_SUCCESS)
2030 {
2031 0 result = GlobusSoapMessageErrorFailedTransport(
2032 result, "Failed to begin reading SOAP message");
2033 0 goto exit;
2034 }
2035 }
2036
2037 11451 exit:
2038
2039 11451 if(result != GLOBUS_SUCCESS)
2040 {
2041
2042 4 callback_handle->callback(result, callback_handle->args);
2043 4 free(callback_handle);
2044 }
2045
2046 11451 GlobusSoapMessageDebugExit();
2047 return;
2048 }
2049
2050 static
2051 void
2052 globus_l_soap_message_response_ready_callback(
2053 globus_xio_handle_t handle,
2054 globus_result_t result,
2055 globus_byte_t * buffer,
2056 globus_size_t len,
2057 globus_size_t nbytes,
2058 globus_xio_data_descriptor_t data_desc,
2059 void * user_arg)
2060 11451 {
2061 globus_soap_message_handle_t message_handle;
2062 int response_code;
2063 const char * message;
2064 globus_xio_http_version_t version;
2065 globus_hashtable_t headers;
2066 GlobusFuncName(globus_l_soap_message_response_ready_callback);
2067 11451 GlobusSoapMessageDebugEnter();
2068
2069 11451 message_handle = (globus_soap_message_handle_t) user_arg;
2070
2071 11451 if (result == GLOBUS_SUCCESS)
2072 {
2073 11447 result = globus_xio_data_descriptor_cntl(
2074 data_desc,
2075 globus_i_soap_message_http_driver,
2076 GLOBUS_XIO_HTTP_GET_RESPONSE,
2077 &response_code,
2078 &message,
2079 &version,
2080 &headers);
2081 }
2082
2083 11451 if(result != GLOBUS_SUCCESS)
2084 {
2085 4 message_handle->result = GlobusSoapMessageErrorFailedTransport(
2086 result, "Error in HTTP response");
2087 4 response_code = -1;
2088 4 GlobusSoapMessageDebugError(message_handle->result);
2089 }
2090 11451 GlobusSoapMessageDebugPrintf(GLOBUS_SOAP_MESSAGE_DEBUG_DEBUG,
2091 ("response code: %d\n", response_code));
2092
2093
2094 11451 if(response_code > 299)
2095 {
2096 6 if(response_code > 399 && response_code < 500)
2097 {
2098 4 message_handle->result = GlobusSoapMessageErrorBadRequest(
2099 response_code, message);
2100 }
2101
2102 6 if(response_code > 499)
2103 {
2104 2 message_handle->result = GlobusSoapMessageErrorFailedResponse(
2105 response_code, message);
2106 }
2107 }
2108
2109 11451 globus_mutex_lock(&message_handle->mutex);
2110 11451 message_handle->response_semaphore++;
2111
2112 22902 if(message_handle->response_semaphore > 1 &&
2113 message_handle->response_handle)
2114 {
2115 globus_l_soap_message_callback_handle_t * response_handle =
2116 (globus_l_soap_message_callback_handle_t *)
2117 11451 message_handle->response_handle;
2118
2119 11451 globus_mutex_unlock(&message_handle->mutex);
2120
2121 11451 message_handle->response_handle = NULL;
2122
2123 11451 globus_l_soap_message_response_callback(
2124 response_handle);
2125 }
2126 else
2127 {
2128 0 globus_mutex_unlock(&message_handle->mutex);
2129 }
2130
2131 11451 GlobusSoapMessageDebugExit();
2132 return;
2133 }
2134
2135 static
2136 globus_bool_t
2137 globus_l_soap_message_timeout_callback(
2138 globus_xio_handle_t handle,
2139 globus_xio_operation_type_t type,
2140 void * user_arg)
2141 0 {
2142 0 return GLOBUS_TRUE;
2143 }
2144
2145
2146 static
2147 void
2148 globus_l_soap_message_register_close_callback(
2149 globus_xio_handle_t handle,
2150 globus_result_t result,
2151 void * args)
2152 16522 {
2153 globus_l_soap_message_close_callback_t * callback_handle;
2154
2155 16522 callback_handle = (globus_l_soap_message_close_callback_t *) args;
2156
2157 16522 callback_handle->callback(result, callback_handle->args);
2158
2159 16522 free(callback_handle);
2160 16522 }
2161
2162 static
2163 globus_result_t
2164 globus_l_authz_host_self(
2165 globus_soap_message_handle_t message,
2166 globus_soap_message_auth_method_t authn)
2167 0 {
2168 globus_result_t result;
2169 const char * endpoint;
2170 0 globus_object_t * host_error = NULL;
2171 0 globus_object_t * self_error = NULL;
2172 gss_name_t desired_name;
2173 gss_name_t peer_name;
2174 OM_uint32 maj_stat, min_stat;
2175 int equal;
2176
2177 0 if (authn == GLOBUS_SOAP_MESSAGE_AUTH_SECURE_MESSAGE)
2178 {
2179 0 peer_name = (gss_name_t) globus_soap_message_attr_get(
2180 message->attrs,
2181 GLOBUS_SOAP_MESSAGE_PEER_IDENTITY_KEY);
2182 }
2183 else
2184 {
2185 /* Peer name from XIO */
2186 0 result = globus_xio_handle_cntl(
2187 message->xio_handle,
2188 globus_i_soap_message_gsi_driver,
2189 GLOBUS_XIO_GSI_GET_PEER_NAME,
2190 &peer_name);
2191 0 if (result != GLOBUS_SUCCESS)
2192 {
2193 0 goto exit;
2194 }
2195 }
2196 0 if (peer_name == GSS_C_NO_NAME)
2197 {
2198 0 result = globus_error_put(
2199 globus_error_construct_multiple(
2200 GLOBUS_SOAP_MESSAGE_MODULE,
2201 GLOBUS_SOAP_MESSAGE_ERROR_TYPE_AUTHORIZATION_FAILED,
2202 "Host/Self authorization failed: Can't determine peer name"));
2203 0 goto exit;
2204 }
2205
2206 /* First try host authz */
2207 0 endpoint = globus_soap_message_handle_get_attr(
2208 message,
2209 GLOBUS_SOAP_MESSAGE_SERVICE_ENDPOINT_KEY);
2210
2211 0 result = globus_l_create_name_from_url(endpoint, &desired_name);
2212 0 if (result != GLOBUS_SUCCESS)
2213 {
2214 0 host_error = globus_error_get(result);
2215 0 goto self_authz;
2216 }
2217 0 if (desired_name == GSS_C_NO_NAME)
2218 {
2219 0 host_error = globus_error_construct_multiple(
2220 GLOBUS_SOAP_MESSAGE_MODULE,
2221 GLOBUS_SOAP_MESSAGE_ERROR_TYPE_AUTHORIZATION_FAILED,
2222 "Host authorization failed: Can't determine peer name");
2223 0 goto self_authz;
2224 }
2225 0 maj_stat = gss_compare_name(
2226 &min_stat,
2227 desired_name,
2228 peer_name,
2229 &equal);
2230
2231 0 if (GSS_ERROR(maj_stat))
2232 {
2233 0 host_error = globus_error_construct_gssapi_error(
2234 GLOBUS_GSI_GSSAPI_MODULE,
2235 NULL,
2236 min_stat,
2237 maj_stat);
2238 0 equal = GLOBUS_FALSE;
2239 }
2240 0 gss_release_name(&min_stat, &desired_name);
2241 0 if (equal)
2242 {
2243 0 goto exit;
2244 }
2245 else
2246 {
2247 0 host_error = globus_error_construct_error(
2248 GLOBUS_SOAP_MESSAGE_MODULE,
2249 NULL,
2250 GLOBUS_SOAP_MESSAGE_ERROR_TYPE_AUTHORIZATION_FAILED,
2251 __FILE__,
2252 "",
2253 __LINE__,
2254 "Host authorization failed: Name comparison fails");
2255 0 goto self_authz;
2256 }
2257
2258 0 self_authz:
2259 0 result = globus_xio_handle_cntl(
2260 message->xio_handle,
2261 globus_i_soap_message_gsi_driver,
2262 GLOBUS_XIO_GSI_GET_LOCAL_NAME,
2263 &desired_name);
2264 0 if (result != GLOBUS_SUCCESS)
2265 {
2266 0 self_error = globus_error_get(result);
2267 0 goto error;
2268
2269 }
2270 0 if (desired_name == GSS_C_NO_NAME)
2271 {
2272 0 self_error = globus_error_construct_multiple(
2273 GLOBUS_SOAP_MESSAGE_MODULE,
2274 GLOBUS_SOAP_MESSAGE_ERROR_TYPE_AUTHORIZATION_FAILED,
2275 "Host authorization failed: Can't determine peer name");
2276 0 goto error;
2277 }
2278 0 maj_stat = gss_compare_name(
2279 &min_stat,
2280 desired_name,
2281 peer_name,
2282 &equal);
2283
2284 0 if (GSS_ERROR(maj_stat))
2285 {
2286 0 self_error = globus_error_construct_gssapi_error(
2287 GLOBUS_GSI_GSSAPI_MODULE,
2288 NULL,
2289 min_stat,
2290 maj_stat);
2291 0 equal = GLOBUS_FALSE;
2292 }
2293 0 if (equal)
2294 {
2295 0 goto exit;
2296 }
2297 else
2298 {
2299 0 self_error = globus_error_construct_error(
2300 GLOBUS_SOAP_MESSAGE_MODULE,
2301 NULL,
2302 GLOBUS_SOAP_MESSAGE_ERROR_TYPE_AUTHORIZATION_FAILED,
2303 __FILE__,
2304 "",
2305 __LINE__,
2306 "Self authorization failed: Name comparison fails");
2307 }
2308
2309 0 if (host_error || self_error)
2310 {
2311 globus_object_t * error;
2312 0 error:
2313 0 error = globus_error_construct_multiple(
2314 GLOBUS_SOAP_MESSAGE_MODULE,
2315 GLOBUS_SOAP_MESSAGE_ERROR_TYPE_AUTHORIZATION_FAILED,
2316 "Host/Self authorization failed");
2317
2318 0 if (host_error)
2319 {
2320 0 globus_error_mutliple_add_chain(
2321 error,
2322 host_error,
2323 "Host authorization failed");
2324 }
2325 0 if (self_error)
2326 {
2327 0 globus_error_mutliple_add_chain(
2328 error,
2329 self_error,
2330 "Self authorization failed");
2331 }
2332 0 result = globus_error_put(error);
2333 }
2334 0 exit:
2335 0 return result;
2336 }
2337
2338 static
2339 globus_result_t
2340 globus_l_create_name_from_url(
2341 const char * url_string,
2342 gss_name_t * name)
2343 0 {
2344 OM_uint32 j, n;
2345 gss_buffer_desc b;
2346 globus_xio_contact_t contact;
2347 globus_result_t result;
2348
2349 0 result = globus_xio_contact_parse(&contact, url_string);
2350 0 if (result)
2351 {
2352 0 goto out;
2353 }
2354
2355 0 b.value = globus_common_create_string("host@%s", contact.host);
2356 0 b.length = strlen(b.value)+1;
2357
2358 0 globus_xio_contact_destroy(&contact);
2359
2360 0 j = gss_import_name(&n, &b, GSS_C_NT_HOSTBASED_SERVICE, name);
2361 0 if (j != GSS_S_COMPLETE)
2362 {
2363 0 result = globus_error_put(
2364 globus_error_construct_gssapi_error(
2365 GLOBUS_GSI_GSSAPI_MODULE,
2366 NULL,
2367 j,
2368 n));
2369 }
2370 0 free(b.value);
2371 0 out:
2372 0 return result;
2373 }
2374 /* globus_l_create_name_from_url() */
2375