(file) Return to PAMAuth.h CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Executor

  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           //%/////////////////////////////////////////////////////////////////////////////
 34           */
 35           
 36           #ifndef Executor_PAMAuth_h
 37           #define Executor_PAMAuth_h
 38           
 39           #if !defined(PEGASUS_PAM_AUTHENTICATION)
 40           # error "Do not include this file without defining PEGASUS_PAM_AUTHENTICATION"
 41           #endif
 42           
 43 kumpf 1.2 #include <sys/types.h>
 44           #include <sys/socket.h>
 45           #include <sys/wait.h>
 46           #include <unistd.h>
 47           #include <stdio.h>
 48           #include <errno.h>
 49           #include <string.h>
 50           #include <Executor/Strlcpy.h>
 51           #include <Executor/Strlcat.h>
 52           #include <security/pam_appl.h>
 53 kumpf 1.4 #include <Executor/Defines.h>
 54           #include <Executor/Socket.h>
 55 kumpf 1.2 
 56           /*
 57           **==============================================================================
 58           **
 59           **     This program is used to authenticate users with the "Basic PAM
 60           **     Authentication" scheme. It was originally written to isolate memory
 61           **     PAM module errors to an external process.
 62           **
 63           **     This header defines two functions that may be called by clients of this
 64           **     process (the parent process).
 65           **
 66 kumpf 1.5 **         PAMAuthenticate()
 67           **         PAMValidateUser()
 68 kumpf 1.2 **
 69 kumpf 1.5 **     Depending on the PEGASUS_USE_PAM_STANDALONE_PROC build flag, these
 70           **     functions either call PAM directly or fork and execute a child process
 71           **     that performs the requested PAM operation and then exits immediately.
 72           **     The parent and child proceses communicate over a local domain socket,
 73           **     created by the parent just before executing the client program.
 74 kumpf 1.2 **
 75 kumpf 1.5 **     These functions are defined in a header file to avoid the need
 76 kumpf 1.2 **     to link a separate client library.
 77           **
 78           **     CAUTION: This program must not depend on any Pegasus libraries since
 79           **     it is used by the executor process.
 80           **
 81           **==============================================================================
 82           */
 83           
 84           /*
 85           **==============================================================================
 86           **
 87           ** CimserveraStart()
 88           **
 89           **     Starts the CIMSERVERA program, returning a socket used to communicate
 90           **     with it.
 91           **
 92           **==============================================================================
 93           */
 94           
 95           static int CimserveraStart(int* sock)
 96           {
 97 kumpf 1.2     int pair[2];
 98               int pid;
 99           
100               /* Get absolute path of CIMSERVERA program. */
101           
102               char path[EXECUTOR_BUFFER_SIZE];
103           
104               if (PEGASUS_PAM_STANDALONE_PROC_NAME[0] == '/')
105                   Strlcpy(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
106               else
107               {
108                   /* Flawfinder: ignore */
109                   const char* home = getenv("PEGASUS_HOME");
110           
111                   if (!home)
112                       return -1;
113           
114                   Strlcpy(path, home, EXECUTOR_BUFFER_SIZE);
115                   Strlcat(path, "/", EXECUTOR_BUFFER_SIZE);
116                   Strlcat(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
117               }
118 kumpf 1.2 
119               /* Create socket pair for communicating with child process. */
120           
121               if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) != 0)
122                   return -1;
123           
124               /* Fork child: */
125           
126               pid = fork();
127           
128               if (pid < 0)
129 kumpf 1.3     {
130                   close(pair[0]);
131                   close(pair[1]);
132 kumpf 1.2         return -1;
133 kumpf 1.3     }
134 kumpf 1.2 
135               /* Child process: */
136           
137               if (pid == 0)
138               {
139                   char sockStr[32];
140                   const char* argv[3];
141           
142                   close(pair[1]);
143           
144                   /* Convert socket number to string. */
145           
146                   sprintf(sockStr, "%d", pair[0]);
147           
148                   /* Build arguments for execv(). */
149           
150                   argv[0] = CIMSERVERA;
151                   argv[1] = sockStr;
152                   argv[2] = 0;
153           
154                   /* Execute child: */
155 kumpf 1.2 
156                   /* Flawfinder: ignore */
157                   execv(path, (char**)argv);
158                   close(pair[0]);
159                   _exit(0);
160               }
161           
162               /* Parent process: */
163           
164               close(pair[0]);
165           
166               *sock = pair[1];
167               return pid;
168           }
169           
170           /*
171           **==============================================================================
172           **
173           ** CimserveraRequest
174           **
175           **==============================================================================
176 kumpf 1.2 */
177           
178           typedef struct CimserveraRequestStruct
179           {
180               char arg0[EXECUTOR_BUFFER_SIZE];
181               char arg1[EXECUTOR_BUFFER_SIZE];
182               char arg2[EXECUTOR_BUFFER_SIZE];
183           }
184           CimserveraRequest;
185           
186           /*
187           **==============================================================================
188           **
189 kumpf 1.4 ** CimserveraResponse
190           **
191           **==============================================================================
192           */
193           
194           typedef struct CimserveraResponseStruct
195           {
196               /* '0' means authentication successful. '-1' means authentication failed. */
197               int status;
198           }
199           CimserveraResponse;
200           
201           /*
202           **==============================================================================
203           **
204 kumpf 1.5 ** CimserveraProcessOperation()
205 kumpf 1.2 **
206           **==============================================================================
207           */
208           
209 kumpf 1.5 static int CimserveraProcessOperation(
210               const char* operationName,
211               const char* username,
212               const char* password)
213 kumpf 1.2 {
214               int sock;
215               int pid;
216               int status;
217           
218               /* Create the CIMSERVERA process. */
219           
220               pid = CimserveraStart(&sock);
221           
222               if (pid == -1)
223                   return -1;
224           
225               /* Send request, get response. */
226           
227               status = 0;
228           
229               do
230               {
231                   CimserveraRequest request;
232 kumpf 1.4         CimserveraResponse response;
233 kumpf 1.2 
234                   /* Send request to CIMSERVERA process. */
235           
236                   memset(&request, 0, sizeof(request));
237 kumpf 1.5         Strlcpy(request.arg0, operationName, EXECUTOR_BUFFER_SIZE);
238 kumpf 1.2         Strlcpy(request.arg1, username, EXECUTOR_BUFFER_SIZE);
239                   Strlcpy(request.arg2, password, EXECUTOR_BUFFER_SIZE);
240           
241 kumpf 1.4         if (SendBlock(sock, &request, sizeof(request)) != sizeof(request))
242 kumpf 1.2         {
243                       status = -1;
244                       break;
245                   }
246           
247 kumpf 1.4         /* Receive response from CIMSERVERA process. */
248           
249                   if (RecvBlock(sock, &response, sizeof(response)) != sizeof(response))
250                   {
251                       status = -1;
252                       break;
253                   }
254 kumpf 1.2 
255 kumpf 1.4         /* Check status. */
256 kumpf 1.2 
257 kumpf 1.4         if (response.status != 0)
258 kumpf 1.2         {
259                       status = -1;
260                       break;
261                   }
262 kumpf 1.4 
263 kumpf 1.5 #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
264                   /* When called from the main cimserver process, the cimservera
265                      exit status must be harvested explicitly to prevent zombies.
266                   */
267 kumpf 1.4 
268 kumpf 1.5         while ((waitpid(pid, 0, 0) == -1) && (errno == EINTR))
269                       ;
270           #endif
271 kumpf 1.2     }
272               while (0);
273           
274               close(sock);
275           
276               return status;
277           }
278           
279           /*
280           **==============================================================================
281           **
282           ** struct PAMData
283           **
284           **     Client data passed to PAM routines.
285           **
286           **==============================================================================
287           */
288           
289           typedef struct PAMDataStruct
290           {
291               const char* password;
292 kumpf 1.2 }
293           PAMData;
294           
295           /*
296           **==============================================================================
297           **
298           ** PAMAuthenticateCallback()
299           **
300           **     Callback used by PAMAuthenticate().
301           **
302           **==============================================================================
303           */
304           
305           static int PAMAuthenticateCallback(
306               int num_msg,
307           #if defined(PEGASUS_OS_LINUX)
308               const struct pam_message** msg,
309           #else
310               struct pam_message** msg,
311           #endif
312               struct pam_response** resp,
313 kumpf 1.2     void* appdata_ptr)
314           {
315               PAMData* data = (PAMData*)appdata_ptr;
316               int i;
317           
318               if (num_msg > 0)
319               {
320                   *resp = (struct pam_response*)calloc(
321                       num_msg, sizeof(struct pam_response));
322           
323                   if (*resp == NULL)
324                       return PAM_BUF_ERR;
325               }
326               else
327                   return PAM_CONV_ERR;
328           
329               for (i = 0; i < num_msg; i++)
330               {
331                   switch (msg[i]->msg_style)
332                   {
333                       case PAM_PROMPT_ECHO_OFF:
334 kumpf 1.2             {
335                           resp[i]->resp = (char*)malloc(PAM_MAX_MSG_SIZE);
336                           Strlcpy(resp[i]->resp, data->password, PAM_MAX_MSG_SIZE);
337                           resp[i]->resp_retcode = 0;
338                           break;
339                       }
340           
341                       default:
342                           return PAM_CONV_ERR;
343                   }
344               }
345           
346               return PAM_SUCCESS;
347           }
348           
349           /*
350           **==============================================================================
351           **
352           ** PAMValidateUserCallback()
353           **
354           **     Callback used by PAMValidateUser().
355 kumpf 1.2 **
356           **==============================================================================
357           */
358           
359           static int PAMValidateUserCallback(
360               int num_msg,
361           #if defined(PEGASUS_OS_LINUX)
362               const struct pam_message** msg,
363           #else
364               struct pam_message** msg,
365           #endif
366               struct pam_response** resp,
367               void* appdata_ptr)
368           {
369               /* Unused */
370               msg = 0;
371           
372               /* Unused */
373               appdata_ptr = 0;
374           
375               if (num_msg > 0)
376 kumpf 1.2     {
377                   *resp = (struct pam_response*)calloc(
378                       num_msg, sizeof(struct pam_response));
379           
380                   if (*resp == NULL)
381                       return PAM_BUF_ERR;
382               }
383               else
384                   return PAM_CONV_ERR;
385           
386               return PAM_SUCCESS;
387           }
388           
389           /*
390           **==============================================================================
391           **
392           ** PAMAuthenticateInProcess()
393           **
394           **     Performs basic PAM authentication on the given username and password.
395           **
396           **==============================================================================
397 kumpf 1.2 */
398           
399           static int PAMAuthenticateInProcess(
400               const char* username, const char* password)
401           {
402               PAMData data;
403               struct pam_conv pconv;
404               pam_handle_t* handle;
405           
406               data.password = password;
407               pconv.conv = PAMAuthenticateCallback;
408               pconv.appdata_ptr = &data;
409           
410           
411               if (pam_start("wbem", username, &pconv, &handle) != PAM_SUCCESS)
412                   return -1;
413           
414               if (pam_authenticate(handle, 0) != PAM_SUCCESS)
415               {
416                   pam_end(handle, 0);
417                   return -1;
418 kumpf 1.2     }
419           
420               if (pam_acct_mgmt(handle, 0) != PAM_SUCCESS)
421               {
422                   pam_end(handle, 0);
423                   return -1;
424               }
425           
426               pam_end(handle, 0);
427           
428               return 0;
429           }
430           
431           /*
432           **==============================================================================
433           **
434           ** PAMValidateUserInProcess()
435           **
436           **     Validate that the *username* refers to a valid PAM user.
437           **
438           **==============================================================================
439 kumpf 1.2 */
440           
441           static int PAMValidateUserInProcess(const char* username)
442           {
443               PAMData data;
444               struct pam_conv pconv;
445               pam_handle_t* phandle;
446           
447               pconv.conv = PAMValidateUserCallback;
448               pconv.appdata_ptr = &data;
449           
450               if (pam_start("wbem", username, &pconv, &phandle) != PAM_SUCCESS)
451                   return -1;
452           
453               if (pam_acct_mgmt(phandle, 0) != PAM_SUCCESS)
454               {
455                   pam_end(phandle, 0);
456                   return -1;
457               }
458           
459               pam_end(phandle, 0);
460 kumpf 1.2 
461               return 0;
462           }
463           
464           /*
465           **==============================================================================
466           **
467           ** PAMAuthenticate()
468           **
469           **     Performs basic PAM authentication on the given username and password.
470           **
471           **==============================================================================
472           */
473           
474           static int PAMAuthenticate(const char* username, const char* password)
475           {
476           #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
477 kumpf 1.5     return CimserveraProcessOperation("authenticate", username, password);
478 kumpf 1.2 #else
479               return PAMAuthenticateInProcess(username, password);
480           #endif
481           }
482           
483           /*
484           **==============================================================================
485           **
486           ** PAMValidateUser()
487           **
488           **     Validate that the *username* refers to a valid PAM user.
489           **
490           **==============================================================================
491           */
492           
493           static int PAMValidateUser(const char* username)
494           {
495           #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
496 kumpf 1.5     return CimserveraProcessOperation("validateUser", username, "");
497 kumpf 1.2 #else
498               return PAMValidateUserInProcess(username);
499           #endif
500           }
501           
502           #endif /* Executor_PAMAuth_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2