1 //%2003////////////////////////////////////////////////////////////////////////
3 // 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.
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // 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 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
16 // 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 // 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 // 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.
24 //==============================================================================
26 // Author: Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
30 //%/////////////////////////////////////////////////////////////////////////////
32 #include <Pegasus/Common/Config.h>
33 #include <Pegasus/Common/System.h>
34 #include <Pegasus/Common/FileSystem.h>
35 #include <Pegasus/Common/Destroyer.h>
36 #include <Pegasus/Common/Base64.h>
37 #include <Pegasus/Common/Exception.h>
38 #include "ClientAuthenticator.h"
43 // Constants used to parse the authentication challenge header
45 #define CHAR_BLANK ' '
47 #define CHAR_QUOTE '"'
52 PEGASUS_NAMESPACE_BEGIN
55 The constant represeting the authentication challenge header.
57 static const String WWW_AUTHENTICATE = "WWW-Authenticate";
60 Constant representing the Basic authentication header.
62 static const String BASIC_AUTH_HEADER = "Authorization: Basic ";
65 Constant representing the Digest authentication header.
67 static const String DIGEST_AUTH_HEADER = "Authorization: Digest ";
70 Constant representing the local authentication header.
72 static const String LOCAL_AUTH_HEADER =
73 "PegasusAuthorization: Local";
76 Constant representing the local privileged authentication header.
78 static const String LOCALPRIVILEGED_AUTH_HEADER =
79 "PegasusAuthorization: LocalPrivileged";
83 ClientAuthenticator::ClientAuthenticator(): _challengeReceived(false)
88 ClientAuthenticator::~ClientAuthenticator()
93 void ClientAuthenticator::clearRequest(Boolean closeConnection)
99 _userName = String::EMPTY;
100 _password = String::EMPTY;
101 _realm = String::EMPTY;
105 Boolean ClientAuthenticator::checkResponseHeaderForChallenge(
106 Array<HTTPHeader> headers)
109 // Search for "WWW-Authenticate" header:
115 if (!HTTPMessage::lookupHeader(
116 headers, WWW_AUTHENTICATE, authHeader, false))
121 if (_challengeReceived)
123 throw UnauthorizedAccess();
127 _challengeReceived = true;
130 // Parse the authentication challenge header
132 if(!_parseAuthHeader(authHeader, authType, authRealm))
134 throw InvalidAuthHeader();
137 if ( String::equal(authType, "LocalPrivileged"))
139 _authType = ClientAuthenticator::LOCALPRIVILEGED;
141 else if ( String::equal(authType, "Local"))
143 _authType = ClientAuthenticator::LOCAL;
145 else if ( String::equal(authType, "Basic"))
147 _authType = ClientAuthenticator::BASIC;
149 else if ( String::equal(authType, "Digest"))
151 _authType = ClientAuthenticator::DIGEST;
155 throw InvalidAuthHeader();
165 String ClientAuthenticator::buildRequestAuthHeader()
167 String challengeResponse = String::EMPTY;
171 case ClientAuthenticator::BASIC:
173 if (_challengeReceived)
175 challengeResponse = BASIC_AUTH_HEADER;
178 // build the credentials string using the
179 // user name and password
181 String userPass = _userName;
183 userPass.append(":");
185 userPass.append(_password);
188 // copy userPass string content to Uint8 array for encoding
190 Array <Uint8> userPassArray;
192 Uint32 userPassLength = userPass.size();
194 userPassArray.reserveCapacity( userPassLength );
195 userPassArray.clear();
197 for( Uint32 i = 0; i < userPassLength; i++ )
199 userPassArray.append( (Uint8)userPass[i] );
203 // base64 encode the user name and password
205 Array <Sint8> encodedArray;
207 encodedArray = Base64::encode( userPassArray );
209 challengeResponse.append(
210 String( encodedArray.getData(), encodedArray.size() ) );
215 //ATTN: Implement Digest Auth challenge handling code here
217 case ClientAuthenticator::DIGEST:
218 // if (_challengeReceived)
220 // challengeResponse = DIGEST_AUTH_HEADER;
225 case ClientAuthenticator::LOCALPRIVILEGED:
227 challengeResponse = LOCALPRIVILEGED_AUTH_HEADER;
228 challengeResponse.append(" \"");
230 if (_userName.size())
232 challengeResponse.append(_userName);
237 // Get the privileged user name on the system
239 challengeResponse.append(System::getPrivilegedUserName());
242 challengeResponse.append(_buildLocalAuthResponse());
246 case ClientAuthenticator::LOCAL:
248 challengeResponse = LOCAL_AUTH_HEADER;
249 challengeResponse.append(" \"");
251 if (_userName.size())
253 challengeResponse.append(_userName);
258 // Get the current login user name
260 challengeResponse.append(System::getEffectiveUserName());
263 challengeResponse.append(_buildLocalAuthResponse());
267 case ClientAuthenticator::NONE:
269 // Gets here only when no authType was set.
271 challengeResponse.clear();
279 return (challengeResponse);
282 void ClientAuthenticator::setRequestMessage(Message* message)
284 _requestMessage = message;
288 Message* ClientAuthenticator::getRequestMessage()
290 return _requestMessage;
294 void ClientAuthenticator::setUserName(const String& userName)
296 _userName = userName;
299 String ClientAuthenticator::getUserName()
304 void ClientAuthenticator::setPassword(const String& password)
306 _password = password;
309 void ClientAuthenticator::setAuthType(ClientAuthenticator::AuthType type)
311 PEGASUS_ASSERT( (type == ClientAuthenticator::BASIC) ||
312 (type == ClientAuthenticator::DIGEST) ||
313 (type == ClientAuthenticator::LOCAL) ||
314 (type == ClientAuthenticator::LOCALPRIVILEGED) ||
315 (type == ClientAuthenticator::NONE) );
320 ClientAuthenticator::AuthType ClientAuthenticator::getAuthType()
325 String ClientAuthenticator::_getFileContent(String filePath)
327 String challenge = String::EMPTY;
330 // Check whether the file exists or not
332 if (!FileSystem::exists(filePath))
334 throw NoSuchFile(filePath);
338 // Open the challenge file and read the challenge data
340 ifstream ifs(filePath.getCString());
343 //ATTN: Log error message
349 while (GetLine(ifs, line))
351 challenge.append(line);
359 String ClientAuthenticator::_buildLocalAuthResponse()
361 String authResponse = String::EMPTY;
363 if (_challengeReceived)
365 authResponse.append(":");
368 // Append the file path that is in the realm sent by the server
370 authResponse.append(_realm);
372 authResponse.append(":");
375 // Read and append the challenge file content
377 String fileContent = String::EMPTY;
380 fileContent = _getFileContent(_realm);
384 //ATTN-NB-04-20000305: Log error message to log file
386 authResponse.append(fileContent);
388 authResponse.append("\"");
390 return (authResponse);
393 Boolean ClientAuthenticator::_parseAuthHeader(
394 const String authHeader,
398 CString header = authHeader.getCString();
399 const char* pAuthHeader = header;
402 // Skip the white spaces in the begining of the header
404 while (*pAuthHeader && isspace(*pAuthHeader))
410 // Get the authentication type
412 String type = _getSubStringUptoMarker(&pAuthHeader, CHAR_BLANK);
420 // Ignore the start quote
422 _getSubStringUptoMarker(&pAuthHeader, CHAR_QUOTE);
426 // Get the realm ending with a quote
428 String realm = _getSubStringUptoMarker(&pAuthHeader, CHAR_QUOTE);
443 String ClientAuthenticator::_getSubStringUptoMarker(
447 String result = String::EMPTY;
450 // Look for the marker
452 const char *pos = strchr(*line, marker);
458 Uint32 length = pos - *line;
460 result.assign(*line, length);
463 while (*pos == marker)
472 result.assign(*line);
474 *line += strlen(*line);
480 PEGASUS_NAMESPACE_END