(file) Return to HTTPAuthenticatorDelegator.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Server

  1 karl  1.27 //%2003////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.27 // Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
  4            // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
  6            // IBM Corp.; EMC Corporation, The Open Group.
  7 mike  1.2  //
  8            // Permission is hereby granted, free of charge, to any person obtaining a copy
  9 kumpf 1.18 // of this software and associated documentation files (the "Software"), to
 10            // deal in the Software without restriction, including without limitation the
 11            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 12 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 13            // furnished to do so, subject to the following conditions:
 14            // 
 15 kumpf 1.18 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 16 mike  1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 17            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 18 kumpf 1.18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 19            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 20            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 21 mike  1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 22            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 23            //
 24            //==============================================================================
 25            //
 26            // Author:  Nag Boranna,   Hewlett-Packard Company(nagaraja_boranna@hp.com)
 27            //
 28 david 1.20 // Modified By: Dave Rosckes (rosckes@us.ibm.com)
 29 kumpf 1.28 //              Sushma Fernandes (sushma_fernandes@hp.com)
 30 h.sterling 1.31.2.2 //              Heather Sterling, IBM (hsterl@us.ibm.com)
 31 mike       1.2      //
 32                     //%/////////////////////////////////////////////////////////////////////////////
 33                     
 34 kumpf      1.10     #include <Pegasus/Common/Constants.h>
 35 mike       1.2      #include <Pegasus/Common/HTTPAcceptor.h>
 36                     #include <Pegasus/Common/HTTPConnection.h>
 37                     #include <Pegasus/Common/HTTPMessage.h>
 38                     #include <Pegasus/Common/XmlWriter.h>
 39                     #include <Pegasus/Config/ConfigManager.h>
 40                     #include "HTTPAuthenticatorDelegator.h"
 41 mday       1.17      
 42 gerarda    1.22     #ifdef PEGASUS_KERBEROS_AUTHENTICATION
 43                     #include <Pegasus/Common/CIMKerberosSecurityAssociation.h>
 44                     #endif 
 45 mike       1.2      
 46                     PEGASUS_USING_STD;
 47                     
 48                     PEGASUS_NAMESPACE_BEGIN
 49                     
 50                     
 51                     HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator(
 52                         Uint32 operationMessageQueueId,
 53                         Uint32 exportMessageQueueId)
 54 kumpf      1.14        : Base(PEGASUS_QUEUENAME_HTTPAUTHDELEGATOR,
 55 kumpf      1.10               MessageQueue::getNextQueueId()),
 56 mike       1.2          _operationMessageQueueId(operationMessageQueueId),
 57                         _exportMessageQueueId(exportMessageQueueId)
 58                     {
 59 kumpf      1.11         PEG_METHOD_ENTER(TRC_HTTP,
 60                             "HTTPAuthenticatorDelegator::HTTPAuthenticatorDelegator");
 61                     
 62 mike       1.2          _authenticationManager = new AuthenticationManager();
 63 kumpf      1.11     
 64                         PEG_METHOD_EXIT();
 65 mike       1.2      }
 66                     
 67                     HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator()
 68                     {
 69 kumpf      1.11         PEG_METHOD_ENTER(TRC_HTTP,
 70                             "HTTPAuthenticatorDelegator::~HTTPAuthenticatorDelegator");
 71                     
 72 mike       1.2          delete _authenticationManager;
 73                     
 74 kumpf      1.11         PEG_METHOD_EXIT();
 75 mike       1.2      }
 76                     
 77 kumpf      1.24     void HTTPAuthenticatorDelegator::enqueue(Message* message) throw(IPCException)
 78                     {
 79                         handleEnqueue(message);
 80                     }
 81                     
 82 mike       1.2      void HTTPAuthenticatorDelegator::_sendResponse(
 83                         Uint32 queueId,
 84                         Array<Sint8>& message)
 85                     {
 86 kumpf      1.11         PEG_METHOD_ENTER(TRC_HTTP,
 87                             "HTTPAuthenticatorDelegator::_sendResponse");
 88                     
 89 mike       1.2          MessageQueue* queue = MessageQueue::lookup(queueId);
 90                     
 91                         if (queue)
 92                         {
 93                             HTTPMessage* httpMessage = new HTTPMessage(message);
 94 h.sterling 1.31.2.2     httpMessage->dest = queue->getQueueId();
 95 kumpf      1.24     
 96 mike       1.2              queue->enqueue(httpMessage);
 97                         }
 98 kumpf      1.11     
 99                         PEG_METHOD_EXIT();
100 mike       1.2      }
101                     
102 gerarda    1.22     #ifdef PEGASUS_KERBEROS_AUTHENTICATION
103                     void HTTPAuthenticatorDelegator::_sendSuccess(
104                         Uint32 queueId,
105                         const String& authResponse)
106                     {
107                         PEG_METHOD_ENTER(TRC_HTTP,
108                             "HTTPAuthenticatorDelegator::_sendSuccess");
109                     
110                         //
111                         // build OK (200) response message
112                         //
113                     
114                         Array<Sint8> message;
115                         XmlWriter::appendOKResponseHeader(message, authResponse);
116                     
117                         _sendResponse(queueId, message);
118                     
119                         PEG_METHOD_EXIT();
120                     }
121                     #endif
122                     
123 mike       1.2      void HTTPAuthenticatorDelegator::_sendChallenge(
124                         Uint32 queueId,
125                         const String& authResponse)
126                     {
127 kumpf      1.11         PEG_METHOD_ENTER(TRC_HTTP,
128                             "HTTPAuthenticatorDelegator::_sendChallenge");
129                     
130 mike       1.2          //
131                         // build unauthorized (401) response message
132                         //
133                     
134                         Array<Sint8> message;
135 kumpf      1.7          XmlWriter::appendUnauthorizedResponseHeader(message, authResponse);
136 mike       1.2      
137                         _sendResponse(queueId, message);
138 kumpf      1.11     
139                         PEG_METHOD_EXIT();
140 mike       1.2      }
141                     
142                     
143 kumpf      1.30     void HTTPAuthenticatorDelegator::_sendHttpError(
144 mike       1.2          Uint32 queueId,
145 kumpf      1.30         const String& status,
146                         const String& cimError,
147                         const String& pegasusError)
148 mike       1.2      {
149 kumpf      1.11         PEG_METHOD_ENTER(TRC_HTTP,
150 kumpf      1.30             "HTTPAuthenticatorDelegator::_sendHttpError");
151 kumpf      1.11     
152 mike       1.2          //
153 kumpf      1.11         // build error response message
154 mike       1.2          //
155                     
156                         Array<Sint8> message;
157 kumpf      1.30         message = XmlWriter::formatHttpErrorRspMessage(
158                             status,
159                             cimError,
160                             pegasusError);
161 mike       1.2      
162                         _sendResponse(queueId, message);
163 kumpf      1.11     
164                         PEG_METHOD_EXIT();
165 mike       1.2      }
166                     
167 mday       1.5      
168                     void HTTPAuthenticatorDelegator::handleEnqueue(Message *message)
169 mike       1.2      {
170 kumpf      1.11         PEG_METHOD_ENTER(TRC_HTTP,
171                             "HTTPAuthenticatorDelegator::handleEnqueue");
172 mike       1.2      
173 kumpf      1.11         if (!message)
174                         {
175                             PEG_METHOD_EXIT();
176 mike       1.2              return;
177 kumpf      1.11         }
178 mike       1.2      
179 kumpf      1.11         // Flag indicating whether the message should be deleted after handling.
180                         // This should be set to false by handleHTTPMessage when the message is
181                         // passed as is to another queue.
182                         Boolean deleteMessage = true;
183 mday       1.5         
184 mike       1.2          if (message->getType() == HTTP_MESSAGE)
185                         {
186                             handleHTTPMessage((HTTPMessage*)message, deleteMessage);
187                         }
188                     
189                         if (deleteMessage)
190                         {
191                             delete message;
192                         }
193 kumpf      1.11     
194                         PEG_METHOD_EXIT();
195 mday       1.5      }
196                     
197                     void HTTPAuthenticatorDelegator::handleEnqueue()
198                     {
199 kumpf      1.11         PEG_METHOD_ENTER(TRC_HTTP,
200                             "HTTPAuthenticatorDelegator::handleEnqueue");
201                     
202 mday       1.5          Message* message = dequeue();
203                         if(message)
204                            handleEnqueue(message);
205 kumpf      1.11     
206                         PEG_METHOD_EXIT();
207 mike       1.2      }
208                     
209                     void HTTPAuthenticatorDelegator::handleHTTPMessage(
210                         HTTPMessage* httpMessage,
211                         Boolean & deleteMessage)
212                     {  
213 kumpf      1.11         PEG_METHOD_ENTER(TRC_HTTP,
214                             "HTTPAuthenticatorDelegator::handleHTTPMessage");
215                     
216 h.sterling 1.31.2.3 #ifdef PEGASUS_USE_232_CLIENT_VERIFICATION
217                         // client may have already authenticated via SSL
218 h.sterling 1.31.2.2     Boolean authenticated = httpMessage->authInfo->getAuthStatus();
219 h.sterling 1.31.2.3 #else
220                         Boolean authenticated = false;
221                     #endif
222 mike       1.2          deleteMessage = true;
223                     
224 h.sterling 1.31.2.3 
225 kumpf      1.13         // ATTN-RK-P3-20020408: This check probably shouldn't be necessary, but
226                         // we're getting an empty message when the client closes the connection
227                         if (httpMessage->message.size() == 0)
228                         {
229                             // The message is empty; just drop it
230 gerarda    1.23             PEG_METHOD_EXIT();
231 kumpf      1.13             return;
232                         }
233                     
234 mike       1.2          //
235                         // get the configured authentication flag
236                         //
237                         ConfigManager* configManager = ConfigManager::getInstance();
238                     
239 kumpf      1.16         Boolean enableAuthentication = false;
240 mike       1.2      
241                         if (String::equal(
242 kumpf      1.16             configManager->getCurrentValue("enableAuthentication"), "true"))
243 mike       1.2          {
244 kumpf      1.16             enableAuthentication = true;
245 mike       1.2          }
246                     
247                         //
248                         // Save queueId:
249                         //
250                         Uint32 queueId = httpMessage->queueId;
251                     
252                         //
253                         // Parse the HTTP message:
254                         //
255                         String startLine;
256                         Array<HTTPHeader> headers;
257                         Uint32 contentLength;
258                     
259                         httpMessage->parse(startLine, headers, contentLength);
260                         
261                         //
262                         // Parse the request line:
263                         //
264                         String methodName;
265                         String requestUri;
266 mike       1.2          String httpVersion;
267 kumpf      1.19         HttpMethod httpMethod = HTTP_METHOD__POST;
268 mike       1.2      
269                         HTTPMessage::parseRequestLine(
270                             startLine, methodName, requestUri, httpVersion);
271                     
272 kumpf      1.19         //
273                         //  Set HTTP method for the request
274                         //
275                         if (methodName == "M-POST")
276                         {
277                             httpMethod = HTTP_METHOD_M_POST;
278                         }
279                     
280 kumpf      1.11         if (methodName != "M-POST" && methodName != "POST")
281                         {
282                             // Only POST and M-POST are implemented by this server
283 kumpf      1.30             _sendHttpError(queueId,
284                                            HTTP_STATUS_NOTIMPLEMENTED);
285 kumpf      1.19         }
286                         else if ((httpMethod == HTTP_METHOD_M_POST) &&
287                                  (httpVersion == "HTTP/1.0"))
288                         {
289                             //
290                             //  M-POST method is not valid with version 1.0
291                             //
292 kumpf      1.30             _sendHttpError(queueId,
293                                            HTTP_STATUS_BADREQUEST);
294 kumpf      1.11         }
295                         else
296                         {
297                             //
298                             // Process M-POST and POST messages:
299                             //
300 h.sterling 1.31.2.2     Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
301                             "HTTPAuthenticatorDelegator - M-POST/POST processing start");
302 mike       1.2      
303 h.sterling 1.31.2.2     httpMessage->message.append('\0');
304 mike       1.2      
305 h.sterling 1.31.2.3 #ifdef PEGASUS_USE_232_CLIENT_VERIFICATION
306 h.sterling 1.31.2.2     if (!authenticated) 
307                         {
308 h.sterling 1.31.2.3 #endif
309 mike       1.2              //
310                             // Search for Authorization header:
311                             //
312                             String authorization = String::EMPTY;
313                     
314                             if ( HTTPMessage::lookupHeader(
315                                  headers, "PegasusAuthorization", authorization, false) &&
316 kumpf      1.16                  enableAuthentication
317 mike       1.2                 )
318                             {
319 kumpf      1.28                 try 
320                                 {
321                                     //
322                                     // Do pegasus/local authentication
323                                     //
324                                     authenticated = 
325                                         _authenticationManager->performPegasusAuthentication(
326                                             authorization,
327                                             httpMessage->authInfo);
328 mike       1.2      
329 kumpf      1.28                     if (!authenticated)
330                                     {
331                                         String authChallenge = String::EMPTY;
332                                         String authResp = String::EMPTY;
333 mike       1.2      
334 kumpf      1.28                         authResp = _authenticationManager->getPegasusAuthResponseHeader(
335                                             authorization,
336                                             httpMessage->authInfo);
337                     
338                                         if (!String::equal(authResp, String::EMPTY))
339                                         {
340                                             _sendChallenge(queueId, authResp);
341                                         }
342                                         else
343                                         {
344 kumpf      1.30                             _sendHttpError(queueId,
345                                                            HTTP_STATUS_BADREQUEST,
346                                                            String::EMPTY,
347                                                            "Authorization header error");
348 kumpf      1.28                         }
349 mike       1.2      
350 kumpf      1.28                         PEG_METHOD_EXIT();
351                                         return;
352 mike       1.2                      }
353 kumpf      1.28                 }
354                                 catch (CannotOpenFile &cof)
355                                 {
356 kumpf      1.30                     _sendHttpError(queueId,
357                                                    HTTP_STATUS_INTERNALSERVERERROR);
358 kumpf      1.11                     PEG_METHOD_EXIT();
359 mike       1.2                      return;
360 kumpf      1.28                     
361 mike       1.2                  }
362                             }
363                     
364 gerarda    1.31     #ifdef PEGASUS_KERBEROS_AUTHENTICATION
365 h.sterling 1.31.2.2     // The presence of a Security Association indicates that Kerberos is being used
366                         // Reset flag for subsequent calls to indicate that no Authorization
367 gerarda    1.31             // record was sent. If one was sent the flag will be appropriately reset later.
368 h.sterling 1.31.2.2     // The sa is maintained while the connection is active.
369 gerarda    1.31             CIMKerberosSecurityAssociation *sa = httpMessage->authInfo->getSecurityAssociation();
370                             if (sa)
371                             {
372                                 sa->setClientSentAuthorization(false);
373                             }
374 h.sterling 1.31.2.2 #endif  
375 gerarda    1.31     
376 mike       1.2              if ( HTTPMessage::lookupHeader(
377                                  headers, "Authorization", authorization, false) &&
378 kumpf      1.16                  enableAuthentication
379 mike       1.2                 )
380                             {
381                                 //
382                                 // Do http authentication if not authenticated already
383                                 //
384                                 if (!authenticated)
385                                 {
386                                     authenticated =
387                                         _authenticationManager->performHttpAuthentication(
388                                             authorization,
389                                             httpMessage->authInfo);
390                     
391                                     if (!authenticated)
392                                     {
393                                         //ATTN: the number of challenges get sent for a 
394                                         //      request on a connection can be pre-set.
395 gerarda    1.22     #ifdef PEGASUS_KERBEROS_AUTHENTICATION
396                                         // Kerberos authentication needs access to the AuthenticationInfo
397                                         // object for this session in order to set up the reference to the
398                                         // CIMKerberosSecurityAssociation object for this session.
399 gerarda    1.23     
400 gerarda    1.22                         String authResp =   
401                                             _authenticationManager->getHttpAuthResponseHeader(httpMessage->authInfo);
402                     #else
403 mike       1.2                          String authResp =
404                                             _authenticationManager->getHttpAuthResponseHeader();
405 gerarda    1.22     #endif
406 kumpf      1.8                          if (!String::equal(authResp, String::EMPTY))
407                                         {
408                                             _sendChallenge(queueId, authResp);
409                                         }
410                                         else
411                                         {
412 kumpf      1.30                             _sendHttpError(queueId,
413                                                            HTTP_STATUS_BADREQUEST,
414                                                            String::EMPTY,
415                                                            "Authorization header error");
416 kumpf      1.8                          }
417 mike       1.2      
418 kumpf      1.11                         PEG_METHOD_EXIT();
419 mike       1.2                          return;
420                                     }
421 h.sterling 1.31.2.2         }  // first not authenticated check
422                         }  // "Authorization" header check
423 gerarda    1.25     
424 gerarda    1.22     #ifdef PEGASUS_KERBEROS_AUTHENTICATION
425 h.sterling 1.31.2.2     // The pointer to the sa is created in the authenticator so we need to also
426                         // assign it here.
427                         sa = httpMessage->authInfo->getSecurityAssociation();
428                         if (sa)
429                         {
430                             Uint32 sendAction = 0;  // 0 - continue, 1 = send success, 2 = send response
431                              // The following is processing to unwrap (decrypt) the request from the
432                              // client when using kerberos authentication.
433                             sa->unwrapRequestMessage(httpMessage->message, contentLength,
434                                          authenticated, sendAction);
435                             if (sendAction)  // send success or send response
436                             {
437                             if (httpMessage->message.size() == 0)
438                             {
439                                 _sendHttpError(queueId,
440                                        HTTP_STATUS_BADREQUEST,
441                                        String::EMPTY,
442                                        "Authorization header error");
443                             }
444                             else
445                             {
446 h.sterling 1.31.2.2             if (sendAction == 1)  // Send success
447                                 {
448                                 _sendSuccess(queueId,
449                                          String(httpMessage->message.getData(), httpMessage->message.size()));
450                                 }
451                     
452                                 if (sendAction == 2)  // Send response
453                                 {
454                                 _sendResponse(queueId, httpMessage->message);
455                                 }
456                             }
457                     
458                             PEG_METHOD_EXIT();
459                             return;
460                             }
461                         }
462 gerarda    1.22     #endif
463 mike       1.2      
464 h.sterling 1.31.2.3 #ifdef PEGASUS_USE_232_CLIENT_VERIFICATION
465 h.sterling 1.31.2.2     } //end BIG if(!authenticated)
466 h.sterling 1.31.2.3 #endif
467 h.sterling 1.31.2.2 
468 kumpf      1.16             if ( authenticated || !enableAuthentication )
469 mike       1.2              {
470                                 //
471                                 // Search for "CIMOperation" header:
472                                 //
473                                 String cimOperation;
474                     
475                                 if (HTTPMessage::lookupHeader(
476 kumpf      1.15                     headers, "CIMOperation", cimOperation, true))
477 mike       1.2                  {
478 h.sterling 1.31.2.2         Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
479                                     "HTTPAuthenticatorDelegator - CIMOperation: $0 ",cimOperation);
480 david      1.21     
481 mike       1.2                      MessageQueue* queue =
482                                         MessageQueue::lookup(_operationMessageQueueId);
483                     
484                                     if (queue)
485                                     {
486 h.sterling 1.31.2.2            httpMessage->dest = queue->getQueueId();
487                                
488                                try
489                                  {
490 kumpf      1.29                            queue->enqueue(httpMessage);
491 h.sterling 1.31.2.2              }
492                                catch(exception & e)
493                                  {
494                                    delete httpMessage;
495 kumpf      1.30                            _sendHttpError(queueId,
496                                                           HTTP_STATUS_REQUEST_TOO_LARGE);
497 h.sterling 1.31.2.2                PEG_METHOD_EXIT();
498                                    deleteMessage = false;
499                                    return;
500                                  }
501 kumpf      1.29                      deleteMessage = false;
502 mike       1.2                      }
503                                 }
504                                 else if (HTTPMessage::lookupHeader(
505 kumpf      1.15                     headers, "CIMExport", cimOperation, true))
506 mike       1.2                  {
507 h.sterling 1.31.2.2         Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
508                                     "HTTPAuthenticatorDelegator - CIMExport: $0 ",cimOperation);
509 david      1.21     
510 mike       1.2                      MessageQueue* queue =
511                                         MessageQueue::lookup(_exportMessageQueueId);
512                     
513                                     if (queue)
514                                     {
515 h.sterling 1.31.2.2            httpMessage->dest = queue->getQueueId();
516 mday       1.6      
517 h.sterling 1.31.2.2            queue->enqueue(httpMessage);
518                                deleteMessage = false;
519 mike       1.2                      }
520                                 }
521                                 else
522                                 {
523 kumpf      1.9                      // We don't recognize this request message type
524                     
525                                     // The Specification for CIM Operations over HTTP reads:
526                                     //
527                                     //     3.3.4. CIMOperation
528                                     //
529                                     //     If a CIM Server receives a CIM Operation request without
530                                     //     this [CIMOperation] header, it MUST NOT process it as if
531                                     //     it were a CIM Operation Request.  The status code
532                                     //     returned by the CIM Server in response to such a request
533                                     //     is outside of the scope of this specification.
534                                     //
535                                     //     3.3.5. CIMExport
536                                     //
537                                     //     If a CIM Listener receives a CIM Export request without
538                                     //     this [CIMExport] header, it MUST NOT process it.  The
539                                     //     status code returned by the CIM Listener in response to
540                                     //     such a request is outside of the scope of this
541                                     //     specification.
542                                     //
543                                     // The author has chosen to send a 400 Bad Request error, but
544 kumpf      1.9                      // without the CIMError header since this request must not be
545                                     // processed as a CIM request.
546                     
547 kumpf      1.30                     _sendHttpError(queueId,
548                                                    HTTP_STATUS_BADREQUEST);
549 kumpf      1.11                     PEG_METHOD_EXIT();
550 mike       1.2                      return;
551 gerarda    1.25                 } // bad request
552                             } // authenticated and enableAuthentication check
553 mike       1.2              else
554 gerarda    1.25             {  // client not authenticated; send challenge
555 gerarda    1.22     #ifdef PEGASUS_KERBEROS_AUTHENTICATION
556                                 String authResp =    
557                                     _authenticationManager->getHttpAuthResponseHeader(httpMessage->authInfo);
558                     #else
559 mike       1.2                  String authResp =
560                                     _authenticationManager->getHttpAuthResponseHeader();
561 gerarda    1.22     #endif
562 mike       1.2      
563 kumpf      1.8                  if (!String::equal(authResp, String::EMPTY))
564                                 {
565                                     _sendChallenge(queueId, authResp);
566                                 }
567                                 else
568                                 {
569 kumpf      1.30                     _sendHttpError(queueId,
570                                                    HTTP_STATUS_BADREQUEST,
571                                                    String::EMPTY,
572                                                    "Authorization header error");
573 kumpf      1.8                  }
574 mike       1.2              }
575 gerarda    1.25         } // M-POST and POST processing
576 kumpf      1.11     
577                         PEG_METHOD_EXIT();
578 mike       1.2      }
579                     
580                     PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2