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

  1 karl  1.34 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.26 // 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 karl  1.22 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.26 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.29 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.34 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15            // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18            // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20 kumpf 1.13 // 
 21 mike  1.2  // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22            // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24            // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27            // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31            //
 32            // Author: Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
 33            //
 34 david.dillard 1.27 // Modified By: David Dillard, VERITAS Software Corp.
 35                    //                  (david.dillard@veritas.com)
 36 joyce.j       1.28 //              Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for PEP-101
 37 mike          1.2  //
 38                    //%/////////////////////////////////////////////////////////////////////////////
 39                    
 40                    #include <Pegasus/Common/Config.h>
 41                    #include <Pegasus/Common/System.h>
 42                    #include <Pegasus/Common/FileSystem.h>
 43 kumpf         1.4  #include <Pegasus/Common/Base64.h>
 44 chuck         1.15 #include <Pegasus/Common/Exception.h>
 45 kumpf         1.18 #include <Pegasus/Common/Constants.h>
 46 mike          1.2  #include "ClientAuthenticator.h"
 47                    
 48 chip          1.7  #include <ctype.h>
 49 kumpf         1.6  
 50 kumpf         1.4  //
 51 kumpf         1.6  // Constants used to parse the authentication challenge header
 52 kumpf         1.4  //
 53 kumpf         1.6  #define CHAR_BLANK     ' '
 54                    
 55                    #define CHAR_QUOTE     '"'
 56                    
 57 kumpf         1.4  
 58 mike          1.2  PEGASUS_USING_STD;
 59                    
 60                    PEGASUS_NAMESPACE_BEGIN
 61                    
 62 kumpf         1.4  /**
 63                        The constant represeting the authentication challenge header.
 64                    */
 65                    static const String WWW_AUTHENTICATE            = "WWW-Authenticate";
 66                    
 67                    /**
 68                        Constant representing the Basic authentication header.
 69                    */
 70                    static const String BASIC_AUTH_HEADER           = "Authorization: Basic ";
 71                    
 72                    /**
 73                        Constant representing the Digest authentication header.
 74                    */
 75                    static const String DIGEST_AUTH_HEADER          = "Authorization: Digest ";
 76                    
 77                    /**
 78                        Constant representing the local authentication header.
 79                    */
 80 chip          1.7  static const String LOCAL_AUTH_HEADER           =
 81 kumpf         1.4                               "PegasusAuthorization: Local";
 82                    
 83                    /**
 84                        Constant representing the local privileged authentication header.
 85                    */
 86 chip          1.7  static const String LOCALPRIVILEGED_AUTH_HEADER =
 87 kumpf         1.4                               "PegasusAuthorization: LocalPrivileged";
 88                    
 89                    
 90                    
 91 kumpf         1.21 ClientAuthenticator::ClientAuthenticator()
 92 mike          1.2  {
 93 kumpf         1.24     clear();
 94 mike          1.2  }
 95                    
 96                    ClientAuthenticator::~ClientAuthenticator()
 97                    {
 98                    
 99                    }
100                    
101 kumpf         1.24 void ClientAuthenticator::clear()
102 mike          1.2  {
103 kumpf         1.30     _requestMessage.reset();
104 kumpf         1.24     _userName = String::EMPTY;
105                        _password = String::EMPTY;
106                        _realm = String::EMPTY;
107                        _challengeReceived = false;
108                        _authType = ClientAuthenticator::NONE;
109 mike          1.2  }
110                    
111 kumpf         1.4  Boolean ClientAuthenticator::checkResponseHeaderForChallenge(
112                        Array<HTTPHeader> headers)
113 mike          1.2  {
114                        //
115                        // Search for "WWW-Authenticate" header:
116                        //
117                        String authHeader;
118 kumpf         1.6      String authType;
119                        String authRealm;
120 mike          1.2  
121                        if (!HTTPMessage::lookupHeader(
122 kumpf         1.4          headers, WWW_AUTHENTICATE, authHeader, false))
123 mike          1.2      {
124                            return false;
125                        }
126                    
127 kumpf         1.10     if (_challengeReceived)
128 kumpf         1.6      {
129 kumpf         1.23         // Do not respond to a challenge more than once
130                            return false;
131 kumpf         1.6      }
132 kumpf         1.4      else
133                        {
134 kumpf         1.10        _challengeReceived = true;
135                    
136                           //
137                           // Parse the authentication challenge header
138                           //
139                           if(!_parseAuthHeader(authHeader, authType, authRealm))
140                           {
141                               throw InvalidAuthHeader();
142                           }
143                    
144                           if ( String::equal(authType, "LocalPrivileged"))
145                           {
146                               _authType = ClientAuthenticator::LOCALPRIVILEGED;
147                           }
148                           else if ( String::equal(authType, "Local"))
149                           {
150                               _authType = ClientAuthenticator::LOCAL;
151                           }
152                           else if ( String::equal(authType, "Basic"))
153                           {
154                               _authType = ClientAuthenticator::BASIC;
155 kumpf         1.10        }
156                           else if ( String::equal(authType, "Digest"))
157                           {
158                               _authType = ClientAuthenticator::DIGEST;
159                           }
160                           else
161                           {
162                               throw InvalidAuthHeader();
163                           }
164 kumpf         1.4  
165 kumpf         1.18        if ( _authType == ClientAuthenticator::LOCAL ||
166                               _authType == ClientAuthenticator::LOCALPRIVILEGED )
167                           {
168                               String filePath = authRealm;
169                               FileSystem::translateSlashes(filePath);
170                    
171                               // Check whether the directory is a valid pre-defined directory.
172                               //
173                               Uint32 index = filePath.reverseFind('/');
174                    
175                               if (index != PEG_NOT_FOUND)
176                               {
177                                   String dirName = filePath.subString(0,index);
178                    
179                                   if (!String::equal(dirName, String(PEGASUS_LOCAL_AUTH_DIR)))
180                                   {
181 kumpf         1.23                    // Refuse to respond to the challenge when the file is
182                                       // not in the expected directory
183                                       return false;
184 kumpf         1.18                }
185                               }
186                           }
187                    
188 kumpf         1.10        _realm = authRealm;
189 mike          1.2  
190 kumpf         1.10        return true;
191                       }
192 mike          1.2  }
193                    
194                    
195                    String ClientAuthenticator::buildRequestAuthHeader()
196                    {
197 kumpf         1.6      String challengeResponse = String::EMPTY;
198                    
199 mike          1.2      switch (_authType)
200                        {
201 kumpf         1.4          case ClientAuthenticator::BASIC:
202                    
203                                if (_challengeReceived)
204                                {
205 kumpf         1.6                  challengeResponse = BASIC_AUTH_HEADER;
206                    
207 kumpf         1.4                  //
208                                    // build the credentials string using the
209                                    // user name and password
210                                    //
211                                    String userPass =  _userName;
212                    
213                                    userPass.append(":");
214                    
215                                    userPass.append(_password);
216                    
217                                    //
218                                    // copy userPass string content to Uint8 array for encoding
219                                    //
220 mike          1.31                 Buffer userPassArray;
221 kumpf         1.4  
222                                    Uint32 userPassLength = userPass.size();
223                    
224 kumpf         1.14                 userPassArray.reserveCapacity( userPassLength );
225 kumpf         1.4                  userPassArray.clear();
226                    
227                                    for( Uint32 i = 0; i < userPassLength; i++ )
228                                    {
229 david.dillard 1.27                     userPassArray.append( (char)userPass[i] );
230 kumpf         1.4                  }
231                    
232                                    //
233                                    // base64 encode the user name and password
234                                    //
235 mike          1.31                 Buffer encodedArray;
236 kumpf         1.4  
237                                    encodedArray = Base64::encode( userPassArray );
238                    
239 kumpf         1.6                  challengeResponse.append(
240 kumpf         1.4                      String( encodedArray.getData(), encodedArray.size() ) );
241                                }
242                                break;
243                    
244 chip          1.7          //
245 kumpf         1.4          //ATTN: Implement Digest Auth challenge handling code here
246 chip          1.7          //
247 kumpf         1.9          case ClientAuthenticator::DIGEST:
248 chip          1.7          //    if (_challengeReceived)
249 mike          1.2          //    {
250 kumpf         1.6          //        challengeResponse = DIGEST_AUTH_HEADER;
251 chip          1.7          //
252 mike          1.2          //    }
253 kumpf         1.9              break;
254 mike          1.2  
255                            case ClientAuthenticator::LOCALPRIVILEGED:
256                    
257 kumpf         1.6              challengeResponse = LOCALPRIVILEGED_AUTH_HEADER;
258                                challengeResponse.append(" \"");
259                    
260 chip          1.7              if (_userName.size())
261 kumpf         1.6              {
262                                     challengeResponse.append(_userName);
263                                }
264                                else
265 mike          1.2              {
266 kumpf         1.4                  //
267 kumpf         1.6                  // Get the privileged user name on the system
268 kumpf         1.4                  //
269 kumpf         1.6                  challengeResponse.append(System::getPrivilegedUserName());
270                                }
271                    
272                                challengeResponse.append(_buildLocalAuthResponse());
273                    
274                                break;
275                    
276                            case ClientAuthenticator::LOCAL:
277 mike          1.2  
278 kumpf         1.6              challengeResponse = LOCAL_AUTH_HEADER;
279                                challengeResponse.append(" \"");
280 mike          1.2  
281 chip          1.7              if (_userName.size())
282 kumpf         1.6              {
283                                     challengeResponse.append(_userName);
284                                }
285                                else
286                                {
287 mike          1.2                  //
288 kumpf         1.6                  // Get the current login user name
289 mike          1.2                  //
290 kumpf         1.12                 challengeResponse.append(System::getEffectiveUserName());
291 mike          1.2              }
292 kumpf         1.6  
293                                challengeResponse.append(_buildLocalAuthResponse());
294 mike          1.2  
295                                break;
296                    
297 kumpf         1.9          case ClientAuthenticator::NONE:
298 chip          1.7              //
299 kumpf         1.4              // Gets here only when no authType was set.
300 chip          1.7              //
301 kumpf         1.6              challengeResponse.clear();
302 mike          1.2              break;
303 kumpf         1.9  
304                            default:
305                                PEGASUS_ASSERT(0);
306                                break;
307 mike          1.2      }
308                    
309 kumpf         1.6      return (challengeResponse);
310 mike          1.2  }
311                    
312                    void ClientAuthenticator::setRequestMessage(Message* message)
313                    {
314 kumpf         1.30     _requestMessage.reset(message);
315 mike          1.2  }
316                    
317                    Message* ClientAuthenticator::getRequestMessage()
318                    {
319 kumpf         1.30     return _requestMessage.get();
320                    }
321 chip          1.7  
322 mateus.baur   1.32 void ClientAuthenticator::clearReconnect()
323                    {
324 kumpf         1.33     _requestMessage.reset();
325 mateus.baur   1.32     _realm = String::EMPTY;
326                        _challengeReceived = false;
327                    }
328                    
329 kumpf         1.30 Message* ClientAuthenticator::releaseRequestMessage()
330                    {
331                        return _requestMessage.release();
332 mike          1.2  }
333                    
334                    void ClientAuthenticator::setUserName(const String& userName)
335                    {
336                        _userName = userName;
337                    }
338                    
339                    String ClientAuthenticator::getUserName()
340                    {
341                        return (_userName);
342                    }
343                    
344                    void ClientAuthenticator::setPassword(const String& password)
345                    {
346                        _password = password;
347                    }
348                    
349                    void ClientAuthenticator::setAuthType(ClientAuthenticator::AuthType type)
350                    {
351 kumpf         1.5      PEGASUS_ASSERT( (type == ClientAuthenticator::BASIC) ||
352                             (type == ClientAuthenticator::DIGEST) ||
353                             (type == ClientAuthenticator::LOCAL) ||
354 kumpf         1.9           (type == ClientAuthenticator::LOCALPRIVILEGED) ||
355                             (type == ClientAuthenticator::NONE) );
356 kumpf         1.5  
357 mike          1.2      _authType = type;
358                    }
359                    
360                    ClientAuthenticator::AuthType ClientAuthenticator::getAuthType()
361                    {
362                        return (_authType);
363                    }
364                    
365                    String ClientAuthenticator::_getFileContent(String filePath)
366                    {
367                        String challenge = String::EMPTY;
368 kumpf         1.18 
369                        FileSystem::translateSlashes(filePath);
370 mike          1.2  
371                        //
372 kumpf         1.4      // Check whether the file exists or not
373 mike          1.2      //
374 kumpf         1.4      if (!FileSystem::exists(filePath))
375                        {
376                            throw NoSuchFile(filePath);
377                        }
378 mike          1.2  
379                        //
380                        // Open the challenge file and read the challenge data
381                        //
382 david         1.19 #if defined(PEGASUS_OS_OS400)
383 david         1.25     ifstream ifs(filePath.getCString(), PEGASUS_STD(_CCSID_T(1208)) );
384 david         1.19 #else
385 david         1.25     ifstream ifs(filePath.getCString());
386 david         1.19 #endif
387 mike          1.2      if (!ifs)
388                        {
389 chip          1.7         //ATTN: Log error message
390 mike          1.2          return (challenge);
391                        }
392                    
393                        String line;
394                    
395                        while (GetLine(ifs, line))
396                        {
397                            challenge.append(line);
398                        }
399                    
400                        ifs.close();
401                    
402                        return (challenge);
403                    }
404                    
405 kumpf         1.6  String ClientAuthenticator::_buildLocalAuthResponse()
406                    {
407                        String authResponse = String::EMPTY;
408                    
409 chip          1.7      if (_challengeReceived)
410 kumpf         1.6      {
411                            authResponse.append(":");
412                    
413                            //
414                            // Append the file path that is in the realm sent by the server
415                            //
416                            authResponse.append(_realm);
417                    
418                            authResponse.append(":");
419                    
420                            //
421 chip          1.7          // Read and append the challenge file content
422 kumpf         1.6          //
423                            String fileContent = String::EMPTY;
424                            try
425                            {
426                                fileContent = _getFileContent(_realm);
427                            }
428 kumpf         1.35         catch(NoSuchFile&)
429 kumpf         1.6          {
430                                //ATTN-NB-04-20000305: Log error message to log file
431                            }
432                            authResponse.append(fileContent);
433                        }
434                        authResponse.append("\"");
435                    
436                        return (authResponse);
437                    }
438                    
439                    Boolean ClientAuthenticator::_parseAuthHeader(
440 chip          1.7      const String authHeader,
441                        String& authType,
442 kumpf         1.6      String& authRealm)
443                    {
444 kumpf         1.17     CString header = authHeader.getCString();
445                        const char* pAuthHeader = header;
446 kumpf         1.6  
447                        //
448                        // Skip the white spaces in the begining of the header
449                        //
450                        while (*pAuthHeader && isspace(*pAuthHeader))
451                        {
452                            *pAuthHeader++;
453                        }
454                    
455                        //
456                        // Get the authentication type
457                        //
458                        String type = _getSubStringUptoMarker(&pAuthHeader, CHAR_BLANK);
459                    
460                        if (!type.size())
461                        {
462                            return false;
463                        }
464                    
465                        //
466                        // Ignore the start quote
467 kumpf         1.6      //
468                        _getSubStringUptoMarker(&pAuthHeader, CHAR_QUOTE);
469                    
470                    
471                        //
472                        // Get the realm ending with a quote
473                        //
474                        String realm = _getSubStringUptoMarker(&pAuthHeader, CHAR_QUOTE);
475                    
476                        if (!realm.size())
477                        {
478                            return false;
479                        }
480                    
481                        authType = type;
482                    
483                        authRealm = realm;
484                    
485                        return true;
486                    }
487                    
488 kumpf         1.6  
489                    String ClientAuthenticator::_getSubStringUptoMarker(
490 chip          1.7      const char** line,
491 kumpf         1.6      char marker)
492                    {
493                        String result = String::EMPTY;
494                    
495                        //
496                        // Look for the marker
497                        //
498 kumpf         1.8      const char *pos = strchr(*line, marker);
499 kumpf         1.6  
500                        if (pos)
501                        {
502                            if (*line != NULL)
503                            {
504                                Uint32 length = pos - *line;
505                    
506                                result.assign(*line, length);
507                            }
508                    
509                            while (*pos == marker)
510                            {
511                                ++pos;
512                            }
513                    
514                            *line = pos;
515                        }
516                        else
517                        {
518 kumpf         1.16         result.assign(*line);
519 kumpf         1.6  
520                            *line += strlen(*line);
521                        }
522                    
523                        return result;
524                    }
525 mike          1.2  
526                    PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2