1 kumpf 1.2 /*
2 //%2006////////////////////////////////////////////////////////////////////////
3 //
4 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
5 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
6 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
7 // IBM Corp.; EMC Corporation, The Open Group.
8 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
9 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
10 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
11 // EMC Corporation; VERITAS Software Corporation; The Open Group.
12 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
13 // EMC Corporation; Symantec Corporation; The Open Group.
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining a copy
16 // of this software and associated documentation files (the "Software"), to
17 // deal in the Software without restriction, including without limitation the
18 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
19 // sell copies of the Software, and to permit persons to whom the Software is
20 // furnished to do so, subject to the following conditions:
21 //
22 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
23 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
24 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
25 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
26 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 //%/////////////////////////////////////////////////////////////////////////////
32 */
33 #include "LocalAuth.h"
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/time.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <pthread.h>
43 kumpf 1.2 #include "Defines.h"
44 #include "Strlcpy.h"
45 #include "Strlcat.h"
46 #include "User.h"
47 #include "Random.h"
48 #include "Log.h"
49 #include "User.h"
50
51 #define TOKEN_LENGTH 40
52
53 /*
54 **==============================================================================
55 **
|
56 kumpf 1.3 ** BuildLocalAuthFilePath()
|
57 kumpf 1.2 **
|
58 kumpf 1.3 ** This function generates an appropriate name for a local authentication
59 ** file for the given *user*. The file path has the following format:
|
60 kumpf 1.2 **
61 ** PEGASUS_LOCAL_AUTH_DIR/cimclient_<user>_<timestamp>_<seq>
62 **
63 **==============================================================================
64 */
65
|
66 kumpf 1.3 static void BuildLocalAuthFilePath(
|
67 kumpf 1.2 const char* user,
68 char path[EXECUTOR_BUFFER_SIZE])
69 {
70 static unsigned int _nextSeq = 1;
71 static pthread_mutex_t _nextSeqMutex = PTHREAD_MUTEX_INITIALIZER;
72 unsigned int seq;
73 struct timeval tv;
74 char buffer[EXECUTOR_BUFFER_SIZE];
75
76 /* Assign next sequence number. */
77
78 pthread_mutex_lock(&_nextSeqMutex);
79 seq = _nextSeq++;
80 pthread_mutex_unlock(&_nextSeqMutex);
81
82 /* Get microseconds elapsed since epoch. */
83
84 gettimeofday(&tv, NULL);
85
|
86 kumpf 1.3 /* Build path */
|
87 kumpf 1.2
88 Strlcpy(path, PEGASUS_LOCAL_AUTH_DIR, EXECUTOR_BUFFER_SIZE);
89 Strlcat(path, "/cimclient_", EXECUTOR_BUFFER_SIZE);
90 Strlcat(path, user, EXECUTOR_BUFFER_SIZE);
|
91 kumpf 1.5 sprintf(buffer, "_%u_%u", seq, (unsigned int)(tv.tv_usec / 1000));
|
92 kumpf 1.2 Strlcat(path, buffer, EXECUTOR_BUFFER_SIZE);
|
93 kumpf 1.3 }
94
95 /*
96 **==============================================================================
97 **
98 ** CreateLocalAuthFile()
99 **
100 ** This function creates a local authentication file with the given *path*
101 ** and returns 0 on success.
102 **
103 ** The algorithm:
104 **
105 ** 1. Generate a random token
106 ** (e.g., 8F85CB1129B2B93F77F5CCA16850D659CCD16FE0).
107 **
108 ** 2. Create the file (owner=root, permissions=0400).
109 **
110 ** 3. Write random token to file.
111 **
112 ** 4. Change file owner to *uid* and group to *gid*.
113 **
114 kumpf 1.3 **==============================================================================
115 */
116
117 int CreateLocalAuthFile(
118 const char* path,
119 int uid,
120 int gid)
121 {
122 char token[TOKEN_LENGTH+1];
123 int fd;
|
124 kumpf 1.2
125 /* Generate random token. */
126
127 {
128 unsigned char data[TOKEN_LENGTH/2];
129 FillRandomBytes(data, sizeof(data));
130 RandBytesToHexASCII(data, sizeof(data), token);
131 }
132
133 /* If file already exists, remove it. */
134
135 /* Flawfinder: ignore */
136 if (access(path, F_OK) == 0 && unlink(path) != 0)
137 return -1;
138
139 /* Create the file as read-only by user. */
140
141 fd = open(path, O_WRONLY | O_EXCL | O_CREAT | O_TRUNC, S_IRUSR);
142
143 if (fd < 0)
144 return -1;
145 kumpf 1.2
146 /* Write the random token. */
147
148 if (write(fd, token, TOKEN_LENGTH) != TOKEN_LENGTH)
149 {
150 close(fd);
151 unlink(path);
152 return -1;
153 }
154
155 /* Change owner of file. */
156
157 if (fchown(fd, uid, gid) != 0)
158 {
159 close(fd);
160 unlink(path);
161 return -1;
162 }
163
164 close(fd);
165 return 0;
166 kumpf 1.2 }
167
168 /*
169 **==============================================================================
170 **
171 ** CheckLocalAuthToken()
172 **
173 ** Compare the *token* with the token in the given file. Return 0 if they
174 ** are identical.
175 **
176 **==============================================================================
177 */
178
|
179 kumpf 1.3 int CheckLocalAuthToken(
|
180 kumpf 1.2 const char* path,
181 const char* token)
182 {
183 char buffer[TOKEN_LENGTH+1];
184 int fd;
185
|
186 kumpf 1.3 /* Open the file. */
|
187 kumpf 1.2
188 if ((fd = open(path, O_RDONLY)) < 0)
189 return -1;
190
191 /* Read the token. */
192
193 if (read(fd, buffer, TOKEN_LENGTH) != TOKEN_LENGTH)
194 {
195 close(fd);
196 return -1;
197 }
198
199 buffer[TOKEN_LENGTH] = '\0';
200
201 /* Compare the token. */
202
203 if (strcmp(token, buffer) != 0)
204 {
205 close(fd);
206 return -1;
207 }
208 kumpf 1.2
209 /* Okay! */
210 close(fd);
211 return 0;
212 }
213
214 /*
215 **==============================================================================
216 **
217 ** StartLocalAuthentication()
218 **
219 ** Initiate first phase of local authentication.
220 **
221 **==============================================================================
222 */
223
224 int StartLocalAuthentication(
225 const char* user,
|
226 kumpf 1.3 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
|
227 kumpf 1.2 {
228 /* Get uid: */
229
230 int uid;
231 int gid;
232
233 if (GetUserInfo(user, &uid, &gid) != 0)
234 return -1;
235
|
236 kumpf 1.3 /* Build an appropriate local authentication file path. */
237
238 BuildLocalAuthFilePath(user, challengeFilePath);
239
|
240 kumpf 1.2 /* Create the local authentication file. */
241
|
242 kumpf 1.3 return CreateLocalAuthFile(challengeFilePath, uid, gid);
|
243 kumpf 1.2 }
244
245 /*
246 **==============================================================================
247 **
248 ** FinishLocalAuthentication()
249 **
|
250 kumpf 1.3 ** Initiates second and final phase of local authentication. Returns 0
251 ** if authentication is successful, -1 otherwise.
|
252 kumpf 1.2 **
253 **==============================================================================
254 */
255
256 int FinishLocalAuthentication(
|
257 kumpf 1.3 const char* challengeFilePath,
|
258 kumpf 1.2 const char* response)
259 {
260 /* Check token against the one in the file. */
261
|
262 kumpf 1.3 int rc = CheckLocalAuthToken(challengeFilePath, response);
|
263 kumpf 1.2
|
264 kumpf 1.4 /* Clean up the file now that the authentication is complete. */
265
266 unlink(challengeFilePath);
|
267 kumpf 1.2
268 return rc;
269 }
|