1 martin 1.29 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.30 //
|
3 martin 1.29 // 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.30 //
|
10 martin 1.29 // 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.30 //
|
17 martin 1.29 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.30 //
|
20 martin 1.29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.30 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.29 // 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.30 //
|
28 martin 1.29 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.2 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include "LocalAuthFile.h"
33
|
34 tony 1.5 #include <fstream>
35 #include <errno.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #ifndef PEGASUS_OS_TYPE_WINDOWS
|
39 kumpf 1.25 # include <sys/time.h>
40 # include <unistd.h>
|
41 tony 1.5 #endif
42
43 #include <Pegasus/Common/System.h>
44 #include <Pegasus/Common/FileSystem.h>
45 #include <Pegasus/Common/Tracer.h>
|
46 mike 1.18 #include <Pegasus/Common/Mutex.h>
|
47 tony 1.5 #include <Pegasus/Config/ConfigManager.h>
48
49 #include "LocalAuthFile.h"
50
|
51 ouyang.jian 1.24 #if defined(PEGASUS_OS_TYPE_WINDOWS)
|
52 kumpf 1.25 // srandom() and random() are srand() and rand() on OS/400 and windows
53 # define srandom(x) srand(x)
54 # define random() rand()
|
55 tony 1.5 #endif
56
57
58 PEGASUS_USING_STD;
59
60 PEGASUS_NAMESPACE_BEGIN
61
62 //
63 // Constant representing the random seed for srandom function
64 //
65 const Uint32 RANDOM_SEED = 100;
66
67 //
68 // File path used to create temporary random file
69 //
70 const char TMP_AUTH_FILE_NAME [] = "/cimclient_";
71
72 //
73 // Constant representing the int buffer size
74 //
75 const Uint32 INT_BUFFER_SIZE = 16;
76 tony 1.5
77 //
78 // Constant representing the random device name
79 //
80 const char DEV_URANDOM [] = "/dev/urandom";
81
82 //
|
83 kumpf 1.25 // Constant representing the size of random entropy needed.
84 // Require minimum 160 bits = 20 bytes of randomness.
|
85 tony 1.5 //
|
86 kumpf 1.25 const Uint32 RANDOM_BYTES_NEEDED = 20;
|
87 tony 1.5
88 //
89 // A unique sequence number used in random file name creation.
90 //
91 static Uint32 sequenceCount = 1;
92 static Mutex sequenceCountLock;
93
94
95
96 LocalAuthFile::LocalAuthFile(const String& userName)
|
97 sushma.fernandes 1.23 : _userName(userName)
|
98 tony 1.5 {
99 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::LocalAuthFile()");
100
101 srandom(RANDOM_SEED);
102
103 //
104 // get the configured temporary authentication file path
105 //
|
106 h.sterling 1.12 _authFilePath = PEGASUS_LOCAL_AUTH_DIR;
|
107 tony 1.5
|
108 mike 1.2 #if defined(PEGASUS_OS_TYPE_WINDOWS)
|
109 tony 1.5 System::makeDirectory((const char *)_authFilePath.getCString());
110 #endif
111 _authFilePath.append(TMP_AUTH_FILE_NAME);
112
113 PEG_METHOD_EXIT();
114 }
115
|
116 kumpf 1.25 LocalAuthFile::~LocalAuthFile()
117 {
|
118 tony 1.5 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::~LocalAuthFile()");
119
120 PEG_METHOD_EXIT();
121 }
122
123 //
124 // create a file and make a random token data entry to it.
125 // send the file name back to caller
126 //
127 String LocalAuthFile::create()
128 {
129 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::create()");
130
131 Uint32 secs, milliSecs;
132 Uint32 mySequenceNumber;
133
134 System::getCurrentTime(secs, milliSecs);
135
136 //
137 // extension size is username plus the sequence count
138 //
|
139 a.arora 1.6 {
|
140 kumpf 1.25 AutoMutex autoMut(sequenceCountLock);
141 mySequenceNumber = sequenceCount++;
|
142 a.arora 1.6 } // mutex unlocks here
|
143 tony 1.5
144 char extension[2*INT_BUFFER_SIZE];
145 sprintf(extension,"_%u_%u", mySequenceNumber, milliSecs);
146 extension[strlen(extension)] = 0;
147
|
148 sushma.fernandes 1.23 String filePath;
|
149 tony 1.5
|
150 kumpf 1.25 // Check to see whether a domain was specified. If so, strip the domain
151 // from the local auth file name, since the backslash and '@' are invalid
152 // filename characters. Store this in another variable, since we need to
153 // keep the domain around for the rest of the operations.
154 String fileUserName = _userName;
155 Uint32 index = _userName.find('\\');
156 if (index != PEG_NOT_FOUND)
157 {
158 fileUserName = _userName.subString(index + 1);
159 }
160 else
161 {
162 index = _userName.find('@');
163 if (index != PEG_NOT_FOUND)
164 {
165 fileUserName = _userName.subString(0, index);
166 }
167 }
|
168 h.sterling 1.10
|
169 tony 1.5 filePath.append(_authFilePath);
|
170 h.sterling 1.10 filePath.append(fileUserName);//_userName);
|
171 tony 1.5 filePath.append(extension);
172 CString filePathCString = filePath.getCString();
173
174 //
175 // 1. Create a file name for authentication.
176 //
177 ofstream outfs(filePathCString);
|
178 ouyang.jian 1.24
|
179 tony 1.5 if (!outfs)
180 {
181 // unable to create file
|
182 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
183 kumpf 1.28 MessageLoaderParms(
184 "Security.Authentication.LocalAuthFile.NO_CREATE",
185 "Creation of the local authentication security file"
186 " $0 failed: $1",
187 filePath, strerror(errno)));
|
188 tony 1.5 PEG_METHOD_EXIT();
189 throw CannotOpenFile (filePath);
190 }
191 outfs.clear();
192
193 //
|
194 thilo.boehm 1.13 // 2. Set file permission to read/write by the owner only.
|
195 tony 1.5 //
|
196 thilo.boehm 1.13
|
197 kumpf 1.25 #if defined(PEGASUS_OS_TYPE_WINDOWS)
198 Boolean success =
199 FileSystem::changeFilePermissions(filePath, _S_IREAD | _S_IWRITE);
200 #else
201 Boolean success =
202 FileSystem::changeFilePermissions(filePath, S_IRUSR | S_IWUSR);
203 #endif
204
205 if (!success)
|
206 tony 1.5 {
|
207 kumpf 1.25 // Unable to change the local auth file permissions, remove the file
|
208 tony 1.5 // and throw CannotOpenFile error.
|
209 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
210 kumpf 1.28 MessageLoaderParms(
211 "Security.Authentication.LocalAuthFile.NO_CHMOD",
212 "Changing permissions of the local authentication security "
213 "file $0 failed: $1",
214 filePath, strerror(errno)));
|
215 tony 1.5
216 if (filePath.size())
217 {
218 if (FileSystem::exists(filePath))
219 {
220 FileSystem::removeFile(filePath);
221 }
222 }
223
|
224 thilo.boehm 1.19 PEG_METHOD_EXIT();
|
225 tony 1.5 throw CannotOpenFile (filePath);
226 }
227
228 //
229 // 3. Generate random token and write the token to the file.
230 //
231 String randomToken = _generateRandomTokenString();
232 outfs << randomToken;
|
233 thilo.boehm 1.19
234 // test if the write was successful
235 if (outfs.fail())
236 {
|
237 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
238 kumpf 1.28 MessageLoaderParms(
239 "Security.Authentication.LocalAuthFile.NO_WRITE",
240 "Cannot write security token to the local authentication "
241 "security file $0.",
242 filePath));
|
243 thilo.boehm 1.19
244 if (filePath.size())
245 {
246 if (FileSystem::exists(filePath))
247 {
248 FileSystem::removeFile(filePath);
249 }
250 }
251
252 PEG_METHOD_EXIT();
253 throw CannotOpenFile (filePath);
254
255 }
|
256 kumpf 1.25
|
257 tony 1.5 outfs.close();
258
259 //
|
260 thilo.boehm 1.13 // 4. Set file permission to read only by the owner.
261 //
|
262 kumpf 1.25 #if defined(PEGASUS_OS_TYPE_WINDOWS)
263 success = FileSystem::changeFilePermissions(filePath, _S_IREAD);
264 #else
265 success = FileSystem::changeFilePermissions(filePath, S_IRUSR);
266 #endif
|
267 thilo.boehm 1.13
|
268 kumpf 1.25 if (!success)
|
269 thilo.boehm 1.13 {
|
270 kumpf 1.25 // Unable to change the local auth file permissions, remove the file
|
271 thilo.boehm 1.13 // and throw CannotOpenFile error.
|
272 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
273 kumpf 1.28 MessageLoaderParms(
274 "Security.Authentication.LocalAuthFile.NO_CHMOD",
275 "Changing permissions of the local authentication security "
276 "file $0 failed: $1",
277 filePath, strerror(errno)));
|
278 thilo.boehm 1.13
279 if (filePath.size())
280 {
281 if (FileSystem::exists(filePath))
282 {
283 FileSystem::removeFile(filePath);
284 }
285 }
286
|
287 thilo.boehm 1.19 PEG_METHOD_EXIT();
|
288 thilo.boehm 1.13 throw CannotOpenFile (filePath);
289 }
290
291 //
292 // 5. Change the file owner to the requesting user.
|
293 tony 1.5 //
|
294 msolomon 1.20
295 if (!FileSystem::changeFileOwner(filePath,_userName))
|
296 tony 1.5 {
297 // Unable to change owner on local auth file, remove the file
298 // and throw CannotOpenFile error.
299
|
300 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
|
301 kumpf 1.28 MessageLoaderParms(
302 "Security.Authentication.LocalAuthFile.NO_CHOWN_REQUSER",
303 "Changing ownership of the local authentication "
304 "security file $0 to the requesting user failed: $1",
305 filePath, strerror(errno)));
|
306 thilo.boehm 1.19
|
307 tony 1.5 if (filePath.size())
308 {
309 if (FileSystem::exists(filePath))
310 {
311 FileSystem::removeFile(filePath);
312 }
313 }
314
|
315 thilo.boehm 1.19 PEG_METHOD_EXIT();
|
316 tony 1.5 throw CannotOpenFile (filePath);
317 }
318
|
319 sushma.fernandes 1.23 _secret = randomToken;
|
320 tony 1.5
321 _filePathName = filePath;
322
323 PEG_METHOD_EXIT();
324
|
325 kumpf 1.25 return _filePathName;
|
326 tony 1.5 }
327
328 //
329 // Removes the file that was created
330 //
331 Boolean LocalAuthFile::remove()
332 {
333 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::remove()");
334
335 Boolean retVal = true;
336
337 //
338 // remove the file
339 //
340 if (FileSystem::exists(_filePathName))
341 {
|
342 kumpf 1.25
|
343 a.dunfey 1.22 #if !defined(PEGASUS_OS_TYPE_WINDOWS)
|
344 a.dunfey 1.17 // change ownership back to the CIMOM
|
345 kumpf 1.25 int rc = chown(
346 (const char *)_filePathName.getCString(), geteuid(), getegid());
347
348 if (rc == -1)
349 {
|
350 yi.zhou 1.21 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::WARNING,
|
351 kumpf 1.28 MessageLoaderParms(
352 "Security.Authentication.LocalAuthFile.NO_CHOWN",
353 "Changing ownership of the local authentication "
354 "security file back to the CIMServer UserId failed."));
|
355 marek 1.16 }
|
356 a.dunfey 1.17 #endif
|
357 marek 1.16
|
358 tony 1.5 retVal = FileSystem::removeFile(_filePathName);
359 }
360
361 PEG_METHOD_EXIT();
362
|
363 kumpf 1.25 return retVal;
|
364 tony 1.5 }
365
366 //
|
367 sushma.fernandes 1.23 // Get the string that was created as a secret string
|
368 tony 1.5 //
|
369 sushma.fernandes 1.23 String LocalAuthFile::getSecretString()
|
370 tony 1.5 {
|
371 sushma.fernandes 1.23 PEG_METHOD_ENTER(TRC_AUTHENTICATION, "LocalAuthFile::getSecretString()");
|
372 tony 1.5
373 PEG_METHOD_EXIT();
374
|
375 kumpf 1.25 return _secret;
|
376 tony 1.5 }
377
378
379 //
380 // Generate random token string
381 //
382 String LocalAuthFile::_generateRandomTokenString()
383 {
|
384 kumpf 1.25 PEG_METHOD_ENTER(TRC_AUTHENTICATION,
|
385 tony 1.5 "LocalAuthFile::_generateRandomTokenString()");
386
|
387 sushma.fernandes 1.23 String randomToken;
|
388 tony 1.5
389 String randFile = String(DEV_URANDOM);
390 FILE *fh;
391
392 //
393 // If /dev/urandom exists then read random token from /dev/urandom
394 //
|
395 kumpf 1.25 if ((fh = fopen( (const char *)randFile.getCString(), "r")) != NULL)
|
396 tony 1.5 {
397 char token[RANDOM_BYTES_NEEDED+1];
398
399 setvbuf(fh, NULL, _IONBF, 0); // need unbuffered input
|
400 a.dunfey 1.22 Uint32 n = (Uint32)fread( (unsigned char *)token, 1,
401 RANDOM_BYTES_NEEDED, fh );
|
402 tony 1.5 fclose(fh);
403 token[n]=0;
404
405 randomToken.clear();
406 char hexChar[10];
407
408 for (Uint32 i=0; i < n; i++)
409 {
410 sprintf(hexChar, "%X", (unsigned char)token[i]);
411 randomToken.append(String(hexChar));
412 memset(hexChar, 0x00, sizeof(hexChar));
413 }
414 }
415
416 char token[2*INT_BUFFER_SIZE];
417 Uint32 seconds, milliseconds;
418
419 System::getCurrentTime(seconds, milliseconds);
420
421 //
422 // generate a random token
423 tony 1.5 //
424 char randnum[] = { '0' + (random() % 10), '0' + (random() % 10), '\0' };
425 long randomNum = atol(randnum);
426
|
427 kumpf 1.27 sprintf (token,"%ld%u", randomNum, seconds + milliseconds );
|
428 tony 1.5 token[strlen(token)] = 0;
429
430 randomToken.append(_userName);
431 randomToken.append(token);
432
433 PEG_METHOD_EXIT();
434
|
435 kumpf 1.25 return randomToken;
|
436 tony 1.5 }
437
438 PEGASUS_NAMESPACE_END
|