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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2